django - 使用 FormView 和 ModelForm 更新模型

     2023-02-24     28

关键词:

【中文标题】django - 使用 FormView 和 ModelForm 更新模型【英文标题】:django - update model with FormView and ModelForm 【发布时间】:2014-03-03 14:59:37 【问题描述】:

我不知道如何在FormView 中使用ModelForm 来更新已经存在的实例??

此 URL 上的 POST 表单:r'/object/(?P<pk>)/'

我使用ModelForm(而不是直接使用UpdateView),因为其中一个字段是必需的,我对其进行了清理。

我基本上想在FormView(在POST)中初始化表单时提供kwarg instance=...,以便它绑定到在url中给出pk的对象。但我不知道在哪里做...

class SaveForm(ModelForm):
    somedata = forms.CharField(required=False)
    class Meta:
        model = SomeModel  # with attr somedata
        fields = ('somedata', 'someotherdata')
    def clean_somedata(self):
        return sometransformation(self.cleaned_data['somedata'])

class SaveView(FormView):
    form_class = SaveForm
    def form_valid(self, form):
        # form.instance here would be == SomeModel.objects.get(pk=pk_from_kwargs)
        form.instance.save()
        return ...

【问题讨论】:

我不太明白你为什么不能使用UpdateView。你能发布你的视图代码吗? @jproffitt 清楚为什么我现在不能使用 UpadteView 了吗? 似乎答案在SingleObjectMixin 中(或停止尝试使用django 基于类的通用视图) 不清楚。 UpdateView 继承自 SingleObjectMixin。看来这正是您所需要的。如果您在场地上进行清洁并不重要。您不想用现有数据填充表单吗? 对于可能遇到此问题的其他人:如果您发现必须添加 blank=True, null=True 以使事情得到足够的验证以进行后处理,您最好将模型解耦并表单,只使用表单,然后手动创建模型实例。在许多用例中对我来说效果更好,例如当您需要访问 request.user 时。 【参考方案1】:

您可以使用 FormView 的 post 方法获取发布的数据并使用 form.save() 保存到模型。希望这会有所帮助。

试试这个

    class SaveForm(ModelForm):
    somedata = forms.CharField(required=False)

    class Meta:
        model = SomeModel  # with attr somedata
        fields = ('somedata', 'someotherdata')

    def __init__(self, *args, **kwargs):
        super(SaveForm, self).__init__(*args, **kwargs)

    def save(self, id):
        print id   #this id will be sent from the view
        instance = super(SaveForm, self).save(commit=False)
        instance.save()
        return instance


class SaveView(FormView):
    template_name = 'sometemplate.html'
    form_class = SaveForm

    def post(self, request, *args, **kwargs):

        form = self.form_class(request.POST)

        if form.is_valid():
            form.save(kwargs.get('pk'))
        else:
            return self.form_invalid(form)

【讨论】:

不使用 URL 中的“pk”,这对我没有帮助 检查我已经添加了从视图中获取 pk 到表单中的逻辑。希望这会有所帮助。【参考方案2】:

在与您讨论后,我仍然不明白您为什么不能使用UpdateView。如果我理解正确,这似乎是一个非常简单的用例。您有一个要更新的模型。而且您有一个自定义表单可以在将其保存到该模型之前进行清理。似乎UpdateView 可以正常工作。像这样:

class SaveForm(ModelForm):
    somedata = forms.CharField(required=False)

    class Meta:
        model = SomeModel  # with attr somedata
        fields = ('somedata', 'someotherdata')

    def clean_somedata(self):
        return sometransformation(self.cleaned_data['somedata'])


class SaveView(UpdateView):
    template_name = 'sometemplate.html'
    form_class = SaveForm
    model = SomeModel

    # That should be all you need. If you need to do any more custom stuff 
    # before saving the form, override the `form_valid` method, like this:

    def form_valid(self, form):
        self.object = form.save(commit=False)

        # Do any custom stuff here

        self.object.save()

        return render_to_response(self.template_name, self.get_context_data())

当然,如果我误解了你,请告诉我。不过你应该可以让它工作。

【讨论】:

很好,我只是没明白我们可以在 UpdateView 中使用 form_class 属性 再想一想,你真的需要self.object = form.save(commit=False)吗? 不,如果您不打算进行任何其他更改,则不这样做。你可以只做self.object = form.save() 并取出self.object.save()。更好的是,您可以删除整个 form_valid 方法。我只是把它放在那里,以防您在将对象保存到数据库之前需要对对象进行任何其他处理。 对,但我的意思是:self.object 在调用form_valid 之前不是已经定义了吗? 是的。但是form_valid 是应该从表单中保存对象的位置。如果您查看ModelFormMixinform_valid 方法(UpdateView 继承自),它就是这样做的:self.object = form.save()。所以要么打电话给super().form_valid,要么自己保存表格。就像我展示的那样。【参考方案3】:

对于此线程的任何其他访问者,是的,您可以创建一个 FormView,其作用类似于 CreateViewUpdateView。尽管有其他用户的一些意见,但如果您希望有一个 单个 表单/URL/页面用于 Web 表单以保存一些用户数据,这些数据可以是可选的,但需要得救一次且只有一次。您不希望为此有 2 个 URL/视图,而只有一个显示表单的页面/URL,如果用户已保存模型,则填充要更新的先前数据。

考虑一种像这样的“接触”模型:

from django.conf import settings
from django.db import models


class Contact(models.Model):
    """
    Contact details for a customer user.
    """
    user = models.OneToOneField(settings.AUTH_USER_MODEL)
    street = models.CharField(max_length=100, blank=True)
    number = models.CharField(max_length=5, blank=True)
    postal_code = models.CharField(max_length=7, blank=True)
    city = models.CharField(max_length=50, blank=True)
    phone = models.CharField(max_length=15)
    alternative_email = models.CharField(max_length=254)

所以,你给它写一个ModelForm,像这样:

from django import forms

from .models import Contact


class ContactForm(forms.ModelForm):
    class Meta:
        model = Contact
        exclude = ('user',)  # We'll set the user later.

您的FormView 同时具有“创建”和“更新”功能将如下所示:

from django.core.urlresolvers import reverse
from django.views.generic.edit import FormView

from .forms import ContactForm
from .models import Contact


class ContactView(FormView):
    template_name = 'contact.html'
    form_class = ContactForm
    success_url = reverse('MY_URL_TO_REDIRECT')

    def get_form(self, form_class):
        """
        Check if the user already saved contact details. If so, then show
        the form populated with those details, to let user change them.
        """
        try:
            contact = Contact.objects.get(user=self.request.user)
            return form_class(instance=contact, **self.get_form_kwargs())
        except Contact.DoesNotExist:
            return form_class(**self.get_form_kwargs())

    def form_valid(self, form):
        form.instance.user = self.request.user
        form.save()
        return super(ContactView, self).form_valid(form)

您甚至不需要在此示例的 URL 中使用 pk,因为该对象是通过 user 一对一字段从数据库中检索的。如果您有类似的情况,其中要创建/更新的模型与用户具有唯一的关系,那就很容易了。

希望这对某人有所帮助...

干杯。

【讨论】:

调用 return super(ContactView, self).form_valid(form) 将涉及 save() 已保存的表单对象。 完美,这很有用,所以我可以避免将用户 ID 放在 url 中! 如果省略 **self.get_form_kwargs() 会发生什么?对我来说,这条线 form_class(instance=contact, **self.get_form_kwargs()) 产生了一些错误,说 instance kwarg got multiple values。

Django:如何使用动态(非模型)数据预填充 FormView?

】Django:如何使用动态(非模型)数据预填充FormView?【英文标题】:Django:Howtopre-populateFormViewwithdynamic(non-model)data?【发布时间】:2014-03-3118:00:20【问题描述】:我有一个FormView视图,使用get_context_data()提供了一些额外的GET上下文... 查看详情

Django mixin 和 FormView 模板与 CBV 混淆

】Djangomixin和FormView模板与CBV混淆【英文标题】:DjangomixinandFormViewtemplateconfusionwithCBV【发布时间】:2019-12-2202:26:05【问题描述】:总的来说,我仍然是mixins的菜鸟,所以我只是想了解这段使用Ajax提交表单的代码中发生了什么。我... 查看详情

重定向到 django FormView 中的下一个 URL

】重定向到djangoFormView中的下一个URL【英文标题】:RedirecttonextURLindjangoFormView【发布时间】:2015-01-1507:16:21【问题描述】:我正在使用Django1.7和Python3.4。我有一个场景,我希望用户在登录后被重定向到另一个视图,如nextGET参数中... 查看详情

使用jquery post时未调用django formview中的post函数

】使用jquerypost时未调用djangoformview中的post函数【英文标题】:postfunctionindjangoformviewnotcalledwhenjquerypostisused【发布时间】:2018-10-0322:24:17【问题描述】:点击“搜索”按钮时,我必须致电SearchView。通过一些打印语句,我可以看到... 查看详情

使用 FormView django 在 form_valid 中渲染模板而不是 success_url

】使用FormViewdjango在form_valid中渲染模板而不是success_url【英文标题】:Renderatemplateinsteadasuccess_urlinform_validwithFormViewdjango【发布时间】:2015-08-2423:06:19【问题描述】:正如标题所说:我需要在提交表单后渲染一个模板,这个表单是... 查看详情

python基于formview类的django视图示例(代码片段)

查看详情

当包含在其他模板中时,Django 通用 FormView 不显示

】当包含在其他模板中时,Django通用FormView不显示【英文标题】:DjangogenericFormViewnotshowingwhenincludedinothertemplate【发布时间】:2018-12-0514:40:21【问题描述】:首先,目前的工作是什么:我在forms.py中定义了一个表单:classEnrollForm(for... 查看详情

将参数传递给FormView Django中的表单

】将参数传递给FormViewDjango中的表单【英文标题】:passingaparametertoaforminFormViewDjango【发布时间】:2018-12-1119:22:53【问题描述】:我有一个名为MyForm的表单。我覆盖了__init__()方法。现在我在MyFormView中创建这个表单时需要传递request... 查看详情

MFC中FormView和Dialog有啥区别?

】MFC中FormView和Dialog有啥区别?【英文标题】:WhatarethedifferencesbetweenFormViewandDialoginMFC?MFC中FormView和Dialog有什么区别?【发布时间】:2013-01-0404:09:56【问题描述】:MFC中FormView和Dialog有什么区别?任何人都可以建议何时使用FormView... 查看详情

使用 FormView 和 ModelForm 时如何在模板上获取 non_field_errors

】使用FormView和ModelForm时如何在模板上获取non_field_errors【英文标题】:Howtogetnon_field_errorsontemplatewhenusingFormViewandModelForm【发布时间】:2014-08-1319:56:42【问题描述】:我正在使用FormView和ModelForm来处理注册表单。如果电子邮件重复... 查看详情

FORMVIEW 和 GET

】FORMVIEW和GET【英文标题】:FORMVIEWandGET【发布时间】:2018-06-2622:02:24【问题描述】:我正在尝试清理FORMVIEW,但收效甚微。我有以下表格:表格...classBookRequestNumberSearch(forms.Form):q=forms.IntegerField(required=True)def__init__(self,*args,**kwargs)... 查看详情

Django递归模型

】Django递归模型【英文标题】:Djangorecursivemodel【发布时间】:2018-05-1219:09:43【问题描述】:我正在使用django为我的项目和文件制作自己的“云服务器”。我正在尝试创建树文件结构,但我不知道如何做到这一点。以及如何制作... 查看详情

Django 内连接查询集

】Django内连接查询集【英文标题】:DjangoInnerJoinQueryset【发布时间】:2013-06-2621:26:33【问题描述】:我正在使用Django,我需要使用两个内部连接来执行查询集。我有三个模型A、B和C,我想在psql中进行如下查询:SELECTDISTINCTaFROMAINNE... 查看详情

在 Django 中屏蔽密码

...一的问题是在输入密码时我无法屏蔽密码。Views.pyclassLoginFormView(FormView):template_name=\'Login/login-page.html\'form_class= 查看详情

在 Django 中,如何在提交 CreateView 时重定向到 UpdateView?

...发布时间】:2019-09-0721:55:09【问题描述】:我创建了一个FormView和模板HTML,我将使用它们来创建和更新模型中的记录。但是,我无法弄清楚如何将CreateView设置为重定向到正在创建的新 查看详情

Django,模型和表单:替换“此字段为必填项”消息

】Django,模型和表单:替换“此字段为必填项”消息【英文标题】:Django,Models&Forms:replace"Thisfieldisrequired"message【发布时间】:2011-07-2002:02:32【问题描述】:我知道在使用普通Django表单时如何设置自己的自定义错误消息... 查看详情

在 FormView 中找不到控件?

】在FormView中找不到控件?【英文标题】:can\'tfindcontrolinFormView?【发布时间】:2011-08-3115:05:41【问题描述】:我需要在FormView控件中找到这个<a>标签,我需要根据条件删除这个标签,但我无法使用FormView.FindControl方法找... 查看详情

FormView.FindControl():对象引用错误

】FormView.FindControl():对象引用错误【英文标题】:FormView.FindControl():objectreferenceerror【发布时间】:2010-12-0121:58:07【问题描述】:我有一个在tr/td中有几个文本框的表单视图。我正在尝试使用.FindControl方法获取文本框,但它返回nu... 查看详情