Python Django ModelForm-是否有一种方法可以动态定义字段,但不能作为最后一个字段?

Python Django ModelForm-是否有一种方法可以动态定义字段,但不能作为最后一个字段?,python,django,django-forms,modelform,django-translated-fields,Python,Django,Django Forms,Modelform,Django Translated Fields,我用Django 2.1创建了一个ModelForm,并将一些字段移到了另一个模型中。调用make_migrations会导致错误,因为当前模型中不存在这些字段。我在表单中添加了一些字段,但其中一个字段是TranslatedField(from),因此当前有2个字段,将来可能会有更多字段,具体取决于语言的数量。该字段的名称为city,目前我收到一条错误消息“为SiteProfile指定的未知字段(city_en,city_he)”(因为我使用的是两种语言—“en”和“he”)—但我希望在项目中使

我用Django 2.1创建了一个
ModelForm
,并将一些字段移到了另一个模型中。调用
make_migrations
会导致错误,因为当前模型中不存在这些字段。我在表单中添加了一些字段,但其中一个字段是
TranslatedField
(from),因此当前有2个字段,将来可能会有更多字段,具体取决于语言的数量。该字段的名称为city,目前我收到一条错误消息“
为SiteProfile指定的未知字段(city_en,city_he)”(因为我使用的是两种语言—“en”和“he”)—但我希望在项目中使用的语言上使用for循环动态创建所有字段。我可以重写(这是一种好的编程方法)
\uuuu new\uuu
方法吗?还是有其他方法?我不喜欢硬编码特定字段名(
city\u en
city\u he
),因为它们将来可能会发生变化,这取决于我们使用的语言数量

您可以在GitHub上看到我当前的(未工作)

以及这一分支的电流

我想知道在一个ModelForm中定义字段动态列表的最佳编程方法是什么(这些字段都是相同的,并且只使用其中一个,另一个在
\uuuuu init\uuuu
方法中删除),其中字段保存在另一个模型中(有两个模型,但只有一个表单)

由于运行make_migrations时出现此错误,我仍然没有提交迁移

(我定义了一个命令
make_migrations
,它只执行
makemigrations

表单(我正在尝试覆盖
\uuuuu new\uuuu
):

更新1:我正在考虑在
类Meta
中将这些字段从
字段中删除的同时,在
初始化方法中定义这些字段,但这是一个好方法吗?要定义不在
字段列表中的字段

Django反对未明确定义字段

强烈建议您显式设置所有 应使用“字段”属性在表单中编辑。做不到 因此,当表单意外更改时,很容易导致安全问题 允许用户设置某些字段,尤其是在创建新字段时 添加到模型中。根据表单的呈现方式,问题 甚至可能在网页上都不可见

另一种方法是自动包含所有字段, 或者只把一些人列入黑名单。众所周知,这一基本方针非常重要 安全性较低,并导致在主要网站(例如。 GitHub)

我想知道是否有一种不需要硬编码语言的解决方案。目前,我硬编码语言:

_city = forms.CharField(label=_('City or locality'), max_length=120, error_messages={'required': _("Please write where you live.")})
city_en = _city
city_he = _city

更新2:我发现我可以通过在表单的
\uuuuu init\uuuuu
方法中添加此行来动态添加此字段:

# Create the localized city field dynamically.
self.fields[to_attribute(name='city')] = forms.CharField(label=_('City or locality'), max_length=120, error_messages={'required': _("Please write where you live.")})

然后将其从
类Meta
中的字段列表和表单本身的硬编码定义中删除。但是,字段是作为表单中的最后一个字段创建的,我希望它在中间。有没有办法在中间添加这个字段?

< p>我不知道这是否会有帮助,但是我有一个调查应用程序,不同的用户希望在背景信息表单上有不同的信息。我通过一个json文件提供它。所以在我的表格里

def __init__(self, *args, **kwargs):
    self.curr_context = kwargs.pop('context', None)
    self.filename = self.get_json_filename()
    super().__init__(*args, **kwargs)
    if os.path.isfile(self.filename) :
        rows = []
        selected_fields = []
        fieldsets = json.load(open(self.filename))
        for fieldset in fieldsets:
            fields = []
            for field in fieldset['fields']:
                if 'field' in field: selected_fields.append(field['field'])
                if 'widget_type' in field:
                    if field['widget_type'] == 'Select': self.fields[field['field']].widget = forms.Select()
                if "choices" in field:
                    choices = []
                    for choice in field['choices']:
                        choices.append((choice['key'],choice['value']))
                    self.fields[field['field']].widget.choices = choices    
                    self.fields[field['field']].choices = choices
                    self.initial[field['field']] = getattr(self.instance, field['field'])
                if 'help' in field:
                    self.fields[field['field']].help_text = field['help']
                if 'html' in field:
                    fields.append(HTML(field['html']))
                if 'divs' in field:
                    fields.append(Field(field['field'], css_class="enabler"))
                    for div in field['divs']:
                        fields.append(Div(Field(div['field'], css_class=div["css"]),*div['div'], css_class="dependent"))
                        selected_fields.append(div['field'])
                        for item in div['div'] : selected_fields.append(item)
                elif 'div' in field:
                    fields.append(Field(field['field'], css_class="enabler"))
                    fields.append(Div(*field['div'], css_class="dependent"))
                    for f in field['div']:
                        selected_fields.append(f)
                else:
                    if 'field' in field: fields.append(field['field'])

            rows.append(Fieldset(fieldset['fieldset'], *fields))
我的json文件将类似于:

[{
    "fieldset" : "Basic Information",
    "fields" : [
        {
            "field" : "form_filler",
            "div" : ["form_filler_other"]
        },{
            "field" : "child_dob"
        },{
            "field" : "age"
        },{
            "field" : "sex"
        },{
            "field" : "country", 
            "div" : ["zip_code"]
        },{
            "field" : "birth_order"
        }, {
            "field" : "multi_birth_boolean",
            "div" : ["multi_birth"]
        }, {
            "field" : "birth_weight_kg",
            "choices" : [
                {
                    "key" : "",
                    "value" : "--------"
                },{ 
                    "key" : "1.0",
                    "value" : "Henry 1"
                },{ 
                    "key" : "2.0",
                    "value" : "Weight 2"
                },{ 
                    "key" : "3.0",
                    "value" : "Weight 3"
                },{ 
                    "key" : "4.0",
                    "value" : "Weight 4"
                }
            ],
            "widget_type" :  "Select"
        }, {
            "field" : "born_on_due_date", 
            "div" : ["early_or_late", "due_date_diff"]
        }

    ]
}, { ...
}]
字段
键是一个输入字段,
div
列表中的项目也是一个输入字段。在这种情况下,当选择字段(BooleanField)时,必须完成
div
列表中的字段,这是我通过clean方法完成的


“我的所有字段”都是在模型中指定的,因此您只能选择要使用的字段

很难理解您到底有什么问题。如果你能回答我下面提出的问题,那将非常有帮助

我将一些字段移到另一个模型

什么领域?哪个型号的?哪种型号? 我假设您正在将
city
字段从
User
模型移动到
SiteProfile

调用
make_migrations
会导致错误,因为这些字段没有 存在于当前模型中

什么错误?当前型号是指什么<代码>站点配置文件
?将场从一个模型移动到另一个模型应该是完全可行的

我已经查看了您的存储库。特别是尝试从
django modeltransation
迁移到
django translated字段的分支。在Github上的
django翻译字段
存储库中也找到了您的问题

不幸的是,我不能完全理解你的问题是什么。 我认为你的问题可以细分为两个独立的问题

  • 迁移不适用于django翻译字段
  • 在表单中动态创建已翻译字段
  • 也许我们可以从迁移开始。
    你说迁移不起作用是什么意思。你能告诉我错误吗

    如果您希望在更改模型时模型的所有字段都动态地显示在ModelForm中,则可以选中此项。(我试过了,效果不错。)

    表单中.py

    def admin_list_display(model_name):
        list = [field.name for field in model_name._meta.get_fields()]
        return list
    
    class EpisodeForm(forms.ModelForm):
        class Meta:
            model = Episode
            fields = admin_list_display(Episode)
    
    ----大警告----

    它将显示不可编辑字段的错误,如(如果您可以更改函数以排除这些类型的字段,请编辑答案):

    如果从中删除
    auto\u now\u add=True
    ,它将正常工作

    注意

    它将为所有选项的ForiegnKeyField创建下拉列表

    更新2:。。。但是,字段是作为表单中的最后一个字段创建的,我希望它在中间。有没有办法在中间添加这个字段?

    发件人:

    如果
    def admin_list_display(model_name):
        list = [field.name for field in model_name._meta.get_fields()]
        return list
    
    class EpisodeForm(forms.ModelForm):
        class Meta:
            model = Episode
            fields = admin_list_display(Episode)
    
    created_at = models.DateTimeField(auto_now_add=True)
    
    django.core.exceptions.FieldError: 'created_at' cannot be specified for Episode model form as it is a non-editable field