直接在视图Django中设置字段外键值

Posted

技术标签:

【中文标题】直接在视图Django中设置字段外键值【英文标题】:Set field foreign key value directly in the view Django 【发布时间】:2015-09-22 21:12:55 【问题描述】:

我有一个名为 record 的模型,但它需要一个外键(条形码),我不想用 select(django 默认执行的方式)将它添加到表单中,而不是我想插入它是手动的,所以我在 forms.py

class add_record_form(forms.ModelForm):
    barcode = forms.CharField()
    class Meta:
        model = Record
        exclude = ('product',)

但我不知道如何将值传递给我的视图并将其添加到记录表中。我收到错误“Record.barcode 必须是条形码的实例”

当我获得条形码实例时,我必须在视图中添加与该条形码关联的产品,这就是我在表单中排除产品字段的原因。

views.py

def add_barcode_view(request):

    if request.method == 'POST':
        formu = add_record_form(request.POST)
        if formu.is_valid():
            bcode = formu.cleaned_data['barcode']
            prod = Producto.objects.get(barcode=bcode)
            cant = formu.cleaned_data['amount']
            aux =  prod.amount - cant
            add = formu.save(commit = False)
            if (aux >= 0):
                prod.amount= aux
                prod.save()
                add.save()
                return HttpResponseRedirect('/record/%s' %add.id)
            else:
                formu = add_record_form(instance = add)
                mensaje = "amount not available"
                ctx = 'men':mensaje, 'form': formu
                return render_to_response('inventario/add_record.html', ctx, context_instance = RequestContext(request))

    else:
        formu = add_record_form()
        ctx = 'form': formu
        return render_to_response('inventario/add_record.html', ctx , context_instance = RequestContext(request))

记录型号和条码 我想在添加记录表单中手动插入条形码的代码

class Barcode(models.Model):
    code            = models.CharField(max_length=13, unique = True)
    date            = models.DateField(auto_now = True)

    def __unicode__(self):
        return self.code

class Record(models.Model):
    barcode         = models.ForeignKey(Barcode)
    record_date     = models.DateField(auto_now = True)
    producto        = models.ForeignKey(Producto)
    amount          = models.IntegerField()
    description     = models.TextField(max_length=150)

追溯

Environment:


Request Method: POST
Request URL: http://localhost:8000/add/record/

Django Version: 1.5.3
Python Version: 2.7.9
Installed Applications:
('django.contrib.auth',
 'django.contrib.contenttypes',
 'django.contrib.sessions',
 'django.contrib.sites',
 'django.contrib.messages',
 'django.contrib.staticfiles',
 'django.contrib.admin',
 'django.contrib.admindocs',
 'sif.apps.home',
 'sif.apps.inventario',
 'sif.apps.web_services.ws_producto',
 'rest_framework')
Installed Middleware:
('django.middleware.common.CommonMiddleware',
 'django.contrib.sessions.middleware.SessionMiddleware',
 'django.middleware.csrf.CsrfViewMiddleware',
 'django.contrib.auth.middleware.AuthenticationMiddleware',
 'django.contrib.messages.middleware.MessageMiddleware')


Traceback:
File "C:\Python27\lib\site-packages\django\core\handlers\base.py" in get_response
  115.                         response = callback(request, *callback_args, **callback_kwargs)
File "D:\MIS DOCUMENTOS\Documents\GitHub\proyecto_formativo\sif\sif\apps\inventario\views.py" in add_record_view
  156.      if formu.is_valid():
File "C:\Python27\lib\site-packages\django\forms\forms.py" in is_valid
  126.         return self.is_bound and not bool(self.errors)
File "C:\Python27\lib\site-packages\django\forms\forms.py" in _get_errors
  117.             self.full_clean()
File "C:\Python27\lib\site-packages\django\forms\forms.py" in full_clean
  274.         self._post_clean()
File "C:\Python27\lib\site-packages\django\forms\models.py" in _post_clean
  315.         self.instance = construct_instance(self, self.instance, opts.fields, opts.exclude)
File "C:\Python27\lib\site-packages\django\forms\models.py" in construct_instance
  52.             f.save_form_data(instance, cleaned_data[f.name])
File "C:\Python27\lib\site-packages\django\db\models\fields\__init__.py" in save_form_data
  466.         setattr(instance, self.name, data)
File "C:\Python27\lib\site-packages\django\db\models\fields\related.py" in __set__
  405.                                  self.field.name, self.field.rel.to._meta.object_name))

Exception Type: ValueError at /add/record/
Exception Value: Cannot assign "u'144253491444'": "Record.barcode" must be a "Barcode" instance.

【问题讨论】:

请向我们展示完整的堆栈跟踪和您的 Record 模型! @ozgur 对不起,现在好多了 【参考方案1】:

首先,您的命名不正确。请遵循PEP8 规则,并使用英文单词来表示变量、类名等所有内容。请将formu 更改为form,将Producto 更改为Product,将add_record_form 更改为AddRecordFormRecordForm

问题是您正在使用字符串而不是实际的Barcode 对象进行数据库查找。另一个问题是,您在创建记录之前没有指定如何获得正确的Product 实例,因此每当创建新条形码时我都会创建一个产品。

你应该更新你的视图函数如下:

def add_barcode_view(request):
    ...
    if formu.is_valid():
        barcode, created = Barcode.objects.get_or_create(
            code=formu.cleaned_data['barcode']
        )
        add = formu.save(commit=False)
        add.barcode = barcode

        prod, created = Producto.objects.get_or_create(barcode=barcode)
        add.producto = prod 
        ...
    ...

【讨论】:

【参考方案2】:

简单的代码如下所示:

    if form.is_valid():
        record = form.save(commit=False)
        record.barcode = barcode
        record.save()

带有commiit=False 的表单的save 方法不会在您的模型对象上触发save,这样您就可以检索准备好保存的对象、为其字段分配一些值或更改某些内容并在此之后保存它。

当然在上面的例子中,条形码应该是Barcode instance。

【讨论】:

你的意思是这样的?因为我仍然收到错误 bcode = formu.cleaned_data['barcode'] record.barcode = Barcode.objects.get(code=bcode) record.save()【参考方案3】:

您需要覆盖add_record_form 中的clean 以避免出现如下错误:

def clean(self):
        barcode = Barcode.objects.get(id=self.cleaned_data.get("barcode"))
        return 'barcode': barcode

【讨论】:

以上是关于直接在视图Django中设置字段外键值的主要内容,如果未能解决你的问题,请参考以下文章

django 插入外键值思路

最初在 django 内联表单集中设置不同的外键值

Django外键查询,为啥它返回None?

在 django 模板中显示外键值

在 Django 中使用 Q 查询外键值

如何清理 Django 孤儿外键值?