Django,将排除的属性添加到提交的模型表单

Posted

技术标签:

【中文标题】Django,将排除的属性添加到提交的模型表单【英文标题】:Django, adding excluded properties to the submitted modelform 【发布时间】:2011-08-15 11:13:37 【问题描述】:

我有一个模型表单,我排除了两个字段,create_datecreated_by 字段。现在使用save() 方法时出现“Not Null”错误,因为created_by 为空。

我尝试在 save() 方法之前将用户 ID 添加到表单中,如下所示:form.cleaned_data['created_by'] = 1form.cleaned_data['created_by_id'] = 1。但这些都不起作用。

有人可以向我解释如何向提交的模型表单“添加”其他内容以便保存吗?

class Location(models.Model):
    name = models.CharField(max_length = 100)
    created_by = models.ForeignKey(User)
    create_date = models.DateTimeField(auto_now=True)

class LocationForm(forms.ModelForm):
    class Meta:
        model = Location
        exclude = ('created_by', 'create_date', )

【问题讨论】:

【参考方案1】:

正确的解决方案是将带有预填充字段的对象实例传递给模型表单的构造函数。这样,这些字段将在验证时填充。如果需要字段,在form.save() 之后分配值可能会导致验证错误。

LocationForm(request.POST or None, instance=Location(
    created_by=request.user,
    create_date=datetime.now(),
))

注意 instance 是一个未保存的对象,所以在表单保存之前不会分配 id。

【讨论】:

我个人觉得这是一个更好的方法【参考方案2】:

由于您在表单中排除了 created_bycreate_date 字段,因此尝试通过 form.cleaned_data 分配它们没有任何意义。

你可以这样做:

如果你有视图,你可以简单地使用form.save(commit=False),然后设置created_by的值

def my_view(request):
    if request.method == "POST":
        form = LocationForm(request.POST)
        if form.is_valid():
            obj = form.save(commit=False)
            obj.created_by = request.user
            obj.save()
        ...
        ...

`

如果您使用的是 Admin,则可以覆盖 save_model() 方法以获得所需的结果。

class LocationAdmin(admin.ModelAdmin):
    def save_model(self, request, obj, form, change):
        obj.created_by = request.user
        obj.save()

【讨论】:

说真的,小马会很自豪的。 以上对我不起作用。在我的 ModelForm Meta 中,我指定了要包含的字段,而不是排除。原来问题是我使用了类变量“include”,而我应该使用“fields”。因此,我想排除的字段被包含在内,并且表单无法验证。【参考方案3】:

一种方法是使用 form.save(commit=False) (doc)

这将返回模型类的对象实例而不将其提交到数据库。

因此,您的处理可能如下所示:

form = some_form(request.POST)
location = form.save(commit=False)
user = User(pk=1)
location.created_by = user
location.create_date = datetime.now()
location.save()

【讨论】:

请注意,您还必须调用表单的 save_m2m() 方法 真,如果模型有多对多关系。【参考方案4】:

将用户作为参数传递给表单构造函数,然后使用它来设置模型实例的 created_by 字段:

def add_location(request):
    ...
    form = LocationForm(user=request.user)
    ...

class LocationForm(forms.ModelForm):
    def __init__(self, *args, **kwargs):
        user = kwargs.pop('user')
        super(forms.ModelForm, self).__init__(*args, **kwargs)
        self.instance.created_by = user

【讨论】:

以上是关于Django,将排除的属性添加到提交的模型表单的主要内容,如果未能解决你的问题,请参考以下文章

将模型范围的帮助文本添加到 django 模型的管理表单

仅具有查看权限的 Django 模型表单将所有字段排除在外

使用 django ajax jquery 提交一个文件不起作用的表单

如何在表单提交之前将多个图像异步添加到 django 表单

Django:将字段添加到模型表单集

django模型表单ModelForm