首页 文章

如何在Django中使用表单字段映射模型字段

提问于
浏览
2

我们有一个包含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'}

1 回答

  • 2

    查看源代码,所有字段都使用关键字参数调用默认表单字段: 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,]+$' . 如果只是验证表单输入,那么该字段似乎真的不会节省很多时间 . 的确,有一条评论说"maybe move to contrib" . 同意..


    决定寻找这个有趣的 . 这是一个 ModelForm 生成器,用新字段覆盖模型字段......它还没有处理kwargs . 这只是我能想到的第一种方法,而不是研究模型生成本身 . 它构造一个常规的 ModelForm 来修改表单/ after / initialization .

    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
    

相关问题