【问题标题】:How to map model fields with form field in Django如何在 Django 中将模型字段与表单字段映射
【发布时间】:2012-05-04 06:44:47
【问题描述】:

我们有一个包含 models.py 的应用程序,其中包含 n 个编号。继承基类的类。我们希望创建从用户 n 保存在 db 中的动态获取值的表单,但问题是我们想使用 django 表单字段而不是 django 模型表单。

我们知道 django 表单中缺少一些字段,例如 PositiveIntegerField、CommaSeparetedIntegerFields 等。我们如何使用 django 表单字段来实现这一点?
如果我们在 shell 中编写以下代码。

from djnago.db import models
mvar = models.PositiveIntegerFields()

from django import forms
fvar = forms.PositiveIntegerFields()
AttributeError: 'module' object has no attribute 'PositiveIntegerField'

forms.py

from django import forms

class ContextForm(forms.Form):
    def __init__(self, rdict, *args, **kwargs):
        super(ContextForm, self).__init__(*args, **kwargs)
        for key in rdict.keys():
            self.fields['%s' % str(key)] = getattr(forms,rdict.get(key))()

rdict = {'address': 'CharField','phone': 'CharField', 'Salary': 'PositiveIntegerField','first name': 'CharField','last name':'CharField'}

【问题讨论】:

  • 你为什么不使用ModelForm并坚持使用标准表格?尽管ModelForm 已经为您提供了所有您想要的东西,但您必须有充分的理由不使用它。
  • 我们可以动态创建ModelForm吗???
  • FormModelForm 都继承自 BaseForm 类,因此具有相似的结构。基本区别在于,您使用Form 定义自己的表单,而ModelForm 使用您的Model 创建表单

标签: django django-models django-forms


【解决方案1】:

查看源代码,该字段所做的只是使用关键字参数调用默认表单字段:min_value

class PositiveIntegerField(IntegerField):
    description = _("Positive integer")

    def get_internal_type(self):
        return "PositiveIntegerField"

    def formfield(self, **kwargs):
        defaults = {'min_value': 0}
        defaults.update(kwargs)
        return super(PositiveIntegerField, self).formfield(**defaults)

因此,您正在寻找的只是

from django import forms
fvar = forms.IntegerField(min_value=0)
fvar.clean(-1)
# ValidationError: [u'Ensure this value is greater than or equal to 0.']

至于CommaSeparatedIntegerField,它看起来像一个CharField,传入了一些django.core.validators.validate_comma_separated_integer_list

f = forms.CharField(validators=[django.core.validators.validate_comma_separated_integer_list])
f.clean('1,2,3')

所有这些都是确保传入的字符串是'^[\d,]+$'。该字段甚至不进行任何 python 转换......如果只是验证表单输入,它似乎并没有真正节省很多时间。事实上,有一条评论说“可能会转向贡献”。同意..


决定研究一下这个是为了好玩。这是一个 ModelForm 生成器,它用新字段覆盖模型字段......它还没有处理 kwargs。这只是我能想到的第一种方法……无需研究模型生成本身。它构造了一个常规的ModelForm,它修改了/after/初始化的形式。

MODEL_FIELD_MAP = {
    models.IntegerField: forms.CharField, 
    # change all IntegerField to forms.CharField
}

def modelform_generator(mymodel):
    class MyModelForm(forms.ModelForm):
        class Meta:
            model = mymodel
        def __init__(self, *args, **kwargs):
            super(MyModelForm, self).__init__(*args, **kwargs)
            for name, form_field in self.fields.items():
                try:
                    model_field = self._meta.model._meta.get_field_by_name(name)[0]
                    # is this a model field?

                    field_override = MODEL_FIELD_MAP.get(model_field.__class__)
                    # do we have this model field mapped to a form field?

                    if field_override:
                        self.fields[name] = field_override()
                        # set the form field to the target field class

                except models.FieldDoesNotExist:
                    pass
    return MyModelForm

【讨论】:

  • 除了这个解决方案之外,还有另一种方法可以将模型字段映射到表单字段,因为为一个字段创建自定义字段很好,但是不在 django 表单中的其余字段呢?而且我们正在创建应该与模型字段映射的动态表单
  • @SweetGirl 这不正是 ModelForms 的用途吗?
  • 我认为这不是一个好主意,但无论如何self._meta.model._meta.get_field_by_name(name)[0]应该在Django的较新版本中更改为self._meta.model._meta.get_field(name)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-02-04
  • 1970-01-01
  • 1970-01-01
  • 2020-11-30
  • 2012-03-09
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多