【问题标题】:How to create generic forms in Django如何在 Django 中创建通用表单
【发布时间】:2014-10-25 16:01:48
【问题描述】:

我正在尝试创建 3 个类来处理我的所有表单。

class FormCreate(CreateView):
    model = MyForm
    fields = ['field_1', 'Field']
    template_name = 'the_path'

class FormUpdate(UpdateView):
    model = MyForm
    fields = ['Field_1', 'Field_2']
    template_name = 'the_path'

class FormDelete(DeleteView):
    model = MyForm
    success_url = reverse_lazy('foo')

我不能为每个不同的 ModelForm 创建 3 个视图,这是重复的,所以我想创建一个基于模型的自定义表单,具有不同的模板和字段:

url(r'admin/gender/add/$', FormCreate.as_view(model=Gender, my_fields, template_name='template_path'), name='gender_add'),

url(r'admin/user/add/$', FormCreate.as_view(model=User, my_fields, template_name='template_path'), name='user_add'),

url(r'admin/company/add/$', FormCreate.as_view(model=Company, my_fields, template_name='template_path'), name='company_add'),

形式不同,作为模板和标签,是否有可能用一个好的url字符串处理这一切?是正确的行为吗?对于那些需要一些自定义的表单,我总是可以继承 CreateForm 并添加我的自定义方法。

提前感谢您的支持!

【问题讨论】:

  • 生成表单可以使用内置的Django modelform_factory docs.djangoproject.com/en/dev/ref/forms/models
  • @madzohan 谢谢,但它不允许传递模板名称、成功 URL 或模型。表单应该由传递给 as_view() 的参数创建。
  • 实际上是这样 - modelform_factory(model, fields=['Field_1', 'Field_2']) 所以你在as_view 中提供了modelfieldstemplatesuccess_url

标签: django django-models django-forms django-views django-class-based-views


【解决方案1】:

您可以使用以下方式生成表单:

def get_custom_form(model, fields):

    class _CustomForm(forms.ModelForm):
        class Meta:
            model = model
            fields = fields

    return _CustomForm

或者使用modelform_factory(model, fields=['Field_1', 'Field_2']),这样你就可以在as_view中提供modelfieldstemplatesuccess_url

在你的 FormCreate 视图覆盖方法get_form_class

class FormCreate(CreateView):
    fields = ['name', 'code']

    def get_form_class(self):
        return modelform_factory(self.model, fields=self.fields)

第二部分,@dukebody 已经回答了,在您的网址中,您可以在as_view 中传递 kwargs:

FormCreate.as_view(model=SomeModel, template_name="some.html", success_url='some_url')

...它们将覆盖默认值。

【讨论】:

  • 我对modelform_factory 更感兴趣,但是如果您提供部分解决方案,则不仅有假设的空间,而且还有混淆的空间。 ricapping: urls.py url(r'admin/gender/add/$', FormCreate.as_view(model=Gender, template_name='path'), name='gender_add'), views.py 我怎么能在这里解决?使用 CreateView 或 modelform_factory() 的子类?这是我的观点:class FormCreate(CreateView): model = none fields = ['name', 'code'] template_name = 'none' 我得到了这个错误:NameError: name 'none' is not defined
  • as_view 是一个类方法,你传递给它的那些 kwargs 是 init kwargs(传递给 View 类的 init 方法)github.com/django/django/blob/master/django/views/generic/… 所以你不需要分配modeltemplate_name 或其他任何东西,如果以后它会被传递给as_view
  • 只需从 FormCreate 的定义中删除 model = nonetemplate_name = 'none' 并将此 kwargs 传递给 as_view 并使用非虚拟值
  • 感谢您的回答,而不是以这种方式工作,我可以在单独的文件中创建我的表单(forms.py - dpaste.com/2T94VJH),以这种方式更新 URLconf:dpaste.com/1FZB63J 和然后更新视图:dpaste.com/2PS19XY 但它会从 base.py 引发错误“template_name”:TemplateResponseMixin 需要定义“template_name”或实现“get_template_names()”
  • 你说要使用 get_form_class(self): 但是当我创建 FormCreate 的实例时,这个方法不会自动调用。
【解决方案2】:

您可以生成它们。添加示例:

models = (Gender, User, Company)
extra_urls = (url(r'admin/' + type(model).__name__ + '/add/$',
                  FormCreate.as_view(
                      model=model,
                      my_fields,
                      template_name='template_path'),
                  name=type(model).__name__ + '_add')
              for model in models)

并将其附加到您的 urlconf。

【讨论】:

  • 我不明白,问题是关于如何将参数传递给 as_view() 方法并接收这些参数以创建不同的表单。例如,为什么在视图函数中这不起作用:model = self.kwargs['model']
【解决方案3】:

默认情况下,as_view() 允许您覆盖直接在类上设置的属性,并且仅覆盖那些。见https://docs.djangoproject.com/en/dev/topics/class-based-views/#simple-usage-in-your-urlconfhttps://github.com/django/django/blob/731f313d604a6cc141f36d8a1ba9a75790c70154/django/views/generic/base.py#L47

如果你想添加更多参数来控制表单的作用,只需将它们放在类定义中:

class FormCreate(CreateView):
    model = MyForm
    fields = ['field_1', 'Field']
    template_name = 'the_path'
    tags = ['tag_1', 'tag_2']
    pony = True

您将能够使用 as_view() 为每种情况覆盖它们。

在视图方法中,将它们称为 self.attrname,而不是 self.kwargs['attrname']。

【讨论】:

  • with model = self.model 我得到了错误:name 'self' is not defined
  • 您需要从 FormCreate 类的方法中读取 self.model。 self 是 Python 中实例方法的约定第一个参数。
  • 嗨,是的,我的问题还在于我是 Python 新手。我刚从 Mark Lutz 的关于 Python 学习类的第 4 章回来。所以,我应该在方法中使用 self.data = data,但是什么方法呢?如果我使用 init 我可以覆盖超类,那么没有通用的模式可以做到这一点吗?
猜你喜欢
  • 2020-12-18
  • 2012-09-17
  • 1970-01-01
  • 1970-01-01
  • 2012-08-20
  • 2015-03-08
  • 1970-01-01
  • 1970-01-01
  • 2020-03-03
相关资源
最近更新 更多