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

时间:2021-03-04 19:19:18

We have one application containing models.py which contains n no. of classes that inherits base class.We want to create form which dynamically takes value from user n saves in db but problem is that we want to use django form fields instead of django model forms.

我们有一个包含模型的应用程序。py包含n no。继承基类的类。我们想要创建的表单可以动态地从db中保存的用户n中获取值,但是问题是我们想使用django表单字段而不是django模型表单。

As we know there are some fields missing in django forms such as PositiveIntegerField, CommaSeparetedIntegerFields etc. How can we achieve this using django form fields?
If we write follwing code in shell.

我们知道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

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 个解决方案

#1


2  

Looking at the source, all the field does is call the default form field with a keyword argument: min_value.

查看源代码,所有字段都使用关键字参数: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)

Therefore what you are looking for is merely

因此,你所寻找的仅仅是

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.']

As for CommaSeparatedIntegerField, it looks like a CharField with some django.core.validators.validate_comma_separated_integer_list passed in.

对于commparatedintegerfield来说,它看起来像一个带有django.core.validators的CharField。validate_comma_separated_integer_list传入。

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

All this does is make sure the passed in string is '^[\d,]+$'. The field doesn't even do any python conversions... it doesn't really seem to save much time if just validates form input. Indeed, there's a comment that says "maybe move to contrib". Agreed..

这是确保传入字符串“^(\ d)+ $ '。这个字段甚至不做任何python转换……如果只验证表单输入,似乎并没有节省多少时间。的确,有一条评论说:“也许你该改变一下。”同意. .


Decided to look into this for fun. Here's a ModelForm generator that overrides model fields with new fields... It doesn't yet handle kwargs. It was just the first method I could think of to do this.. without looking into modelform generation itself. It constructs a regular ModelForm that modifies the form /after/ initialization.

为了好玩,我决定调查一下。这是一个用新字段覆盖模型字段的ModelForm生成器。它还没有处理kwargs。这只是我能想到的第一个方法。不考虑模型生成本身。它构造一个规则的ModelForm来修改表单/之后/初始化。

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

#1


2  

Looking at the source, all the field does is call the default form field with a keyword argument: min_value.

查看源代码,所有字段都使用关键字参数: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)

Therefore what you are looking for is merely

因此,你所寻找的仅仅是

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.']

As for CommaSeparatedIntegerField, it looks like a CharField with some django.core.validators.validate_comma_separated_integer_list passed in.

对于commparatedintegerfield来说,它看起来像一个带有django.core.validators的CharField。validate_comma_separated_integer_list传入。

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

All this does is make sure the passed in string is '^[\d,]+$'. The field doesn't even do any python conversions... it doesn't really seem to save much time if just validates form input. Indeed, there's a comment that says "maybe move to contrib". Agreed..

这是确保传入字符串“^(\ d)+ $ '。这个字段甚至不做任何python转换……如果只验证表单输入,似乎并没有节省多少时间。的确,有一条评论说:“也许你该改变一下。”同意. .


Decided to look into this for fun. Here's a ModelForm generator that overrides model fields with new fields... It doesn't yet handle kwargs. It was just the first method I could think of to do this.. without looking into modelform generation itself. It constructs a regular ModelForm that modifies the form /after/ initialization.

为了好玩,我决定调查一下。这是一个用新字段覆盖模型字段的ModelForm生成器。它还没有处理kwargs。这只是我能想到的第一个方法。不考虑模型生成本身。它构造一个规则的ModelForm来修改表单/之后/初始化。

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