如何在无需重新定义整个表单的情况下使用带有通用 UpdateView 的自定义小部件?

Posted

技术标签:

【中文标题】如何在无需重新定义整个表单的情况下使用带有通用 UpdateView 的自定义小部件?【英文标题】:How does one use a custom widget with a generic UpdateView without having to redefine the entire form? 【发布时间】:2013-05-31 23:38:15 【问题描述】:

我有一个具有 ManyToMany 关系的模型,我想使用 CheckBoxSelectMultiple 小部件对其进行更新,而其他所有内容都使用默认的通用表单,但是当我重新定义该表单字段时,它是唯一显示在 UpdateView 中的字段.有没有一种方法可以使用只有一个字段的小部件而无需重新定义整个表单?

Views.py:

from django.views.generic.edit import UpdateView

from kunden.models import Kunde, Unternehmenstyp
from kunden.forms import KundeEditForm

class KundeUpdate(UpdateView):
    model = Kunde
    form_class =  KundeEditForm
    template_name = 'kunden/kunde_update.html'
    success_url = '/'

forms.py:

from django.forms.widgets import CheckboxSelectMultiple
from django.forms import ModelMultipleChoiceField,ModelForm

from kunden.models import Kunde, Unternehmenstyp

class KundeEditForm(ModelForm):
    model = Kunde
    unternehmenstyp = ModelMultipleChoiceField(widget=CheckboxSelectMultiple,required=True, queryset=Unternehmenstyp.objects.all())

我知道这有一个非常简单的解决方案,所以提前感谢大家的耐心等待。

当我在这里时,有人可以推荐任何值得一读的 django 书籍吗?我已经阅读了基础教程,根据需要挖掘了文档,并阅读了 Django 的两个勺子:https://django.2scoops.org/,所以如果你能为我这个水平的人想一本书,那将不胜感激。再次感谢

【问题讨论】:

【参考方案1】:

这是一个 mixin,它允许您定义一个小部件字典,并且仍然尊重 fields 列表:

from django.forms.models import modelform_factory

class ModelFormWidgetMixin(object):
    def get_form_class(self):
        return modelform_factory(self.model, fields=self.fields, widgets=self.widgets)

可与CreateView、UpdateView等配合使用,例如:

class KundleUpdate(ModelFormWidgetMixin, UpdateView):
    model = Kunde
    widgets = 
        'unternehmenstyp': CheckboxSelectMultiple,
    

【讨论】:

【参考方案2】:

试试这个,class Meta:

from django.forms.widgets import CheckboxSelectMultiple
from django.forms import ModelMultipleChoiceField,ModelForm

from kunden.models import Kunde, Unternehmenstyp

class KundeEditForm(ModelForm):
    class Meta: # model must be in the Meta class
        model = Kunde
    unternehmenstyp = ModelMultipleChoiceField(widget=CheckboxSelectMultiple,required=True, queryset=Unternehmenstyp.objects.all())

参考号:https://docs.djangoproject.com/en/1.5/topics/forms/modelforms/#modelform

如果你只需要做一个简单的覆盖,你也可以使用模型工厂:

from django.views.generic.edit import UpdateView
from django.forms.models import modelform_factory

from kunden.models import Kunde, Unternehmenstyp

class KundeUpdate(UpdateView):
    model = Kunde
    form_class =  modelform_factory(Kunde,
        widgets="unternehmenstyp": CheckboxSelectMultiple )
    template_name = 'kunden/kunde_update.html'
    success_url = '/'

参考号:https://docs.djangoproject.com/en/1.5/topics/forms/modelforms/#modelform-factory-function

【讨论】:

这确实很快。谢谢一堆。我试图接受这个作为答案,但它说我必须等待 10 分钟 :) 无论如何,如果你有时间,你能给我指出一些关于这里发生了什么的文档吗? KundeEditForm 上的元信息让您可以为任何表单字段设置自定义小部件。 对于第二部分,它通过将位置参数“widgets”传递给modelform_factory来做同样的事情。 Django v1.8 要求您将 fieldsexcludes 传递给模型 form_factory。进行更改后(可能有很长的字段列表),代码变得丑陋到我更喜欢 Jonathan Potter 的答案中显示的 ModelFormWidgetMixin。

以上是关于如何在无需重新定义整个表单的情况下使用带有通用 UpdateView 的自定义小部件?的主要内容,如果未能解决你的问题,请参考以下文章

使用 ZF2 组件,无需整个 MVC 流程

如何在不重新加载整个页面的情况下刷新 div?

Django 表单提交无需重新加载页面

AJAX是啥?

带有 Bootstrap 模态视图的 Rails 应用程序,包含表单、提交和消失模态视图,无需重新加载页面

单击带有形式动作的按钮时停止链接转发