Django使用ModelForm更新一个字段

Rom*_*mko 12 python django

如果POST请求只有一个字段作为参数,如何使用ModelForm仅更新实例中的一个字段?ModelField尝试覆盖POST请求中未传递的字段,其中None表示数据丢失.

我有一个+25字段的模型说

class C(models.Model):
    a = models.CharField(max_length=128)
    b = models.CharField(max_length=128)
    ...
    x = models.IntegerField()
Run Code Online (Sandbox Code Playgroud)

我有一个桌面应用程序执行POST请求,以便通过views.py中公开的api方法编辑C的实例

在api方法中,我使用ModelForm来验证字段,如下所示:

form = CModelForm(request.POST, instance=c_instance)
if form.is_valid():
    form.save() 
Run Code Online (Sandbox Code Playgroud)

在执行save()时,django会抱怨某些其他字段不能为null或(如果所有字段都是可选的)用None覆盖它们.

有人知道如何管理吗?我会手动进行所有检查并手动更新,但该模型有如此奇特的长字段列表......

Rom*_*mko 12

得到了这个数字.我所做的是使用实例中的值更新request.POST字典 - 以便自动显示所有未更改的字段.这样做:

from django.forms.models import model_to_dict
from copy import copy

def UPOST(post, obj):
    '''Updates request's POST dictionary with values from object, for update purposes'''
    post = copy(post)
    for k,v in model_to_dict(obj).iteritems():
        if k not in post: post[k] = v
    return post
Run Code Online (Sandbox Code Playgroud)

然后你就是这样做的:

form = CModelForm(UPOST(request.POST,c_instance),instance=c_instance)
Run Code Online (Sandbox Code Playgroud)


rol*_*one 8

您可以通过指定这些字段来使用ModelForm中的字段子集,如下所示:

class PartialAuthorForm(ModelForm):
    class Meta:
        model = Author
        fields = ('name', 'title')
Run Code Online (Sandbox Code Playgroud)

来自文档:

如果在使用ModelForm创建表单时指定字段或排除,则表单的save()方法不会设置不在结果表单中的字段.

https://docs.djangoproject.com/en/dev/topics/forms/modelforms/#using-a-subset-of-fields-on-the-form

  • 问题是我不知道哪个字段会更新: - / (9认同)

NiK*_*iKo 5

我很惊讶还没有人提到modelform_factory

您可以通过创建表单类的特定版本、定义您感兴趣的字段子集来轻松实现部分表单更新:

from django.forms import modelform_factory

...

foo = get_object_or_404(Foo, slug=foo_slug)

if request.method == "POST": 
    PartialFooForm = modelform_factory(
        Foo, form=FooForm, fields=("my_first_field", "my_second_field",)
    )
    form = PartialFooForm(request.POST, instance=foo)
    if form.is_valid():
        foo = form.save()
        return redirect(foo)
else:
    form = FooForm(instance=foo)
Run Code Online (Sandbox Code Playgroud)

  • 谢谢你分享这个,尼科——它就像一个魅力。绝对是我遇到的解决此问题的最佳解决方案。 (2认同)