字段和基本字段 - Django

发布于 2024-08-18 20:43:43 字数 802 浏览 4 评论 0原文

创建平面页面时,我希望用户从预定义列表中选择模板。为了保持 Flatpage 模型不变,我更喜欢 ChoiceField 而不是 ModelChoiceField (后者提供模板的 PK,但我需要名称对于 template_name 字段):

class NewFlatpageForm(FlatpageForm):

    template_name = forms.ChoiceField(choices = [])
    def __init__(self, *args, **kwargs):
        self.base_fields['template_name'].choices = ProjectTemplate.objects.values_list('path', 'name')
        super(NewFlatpageForm, self).__init__(*args, **kwargs)

我覆盖 __init__ 或 Django 在服务器启动时填充选择,然后不会更新列表。

我没有任何管理经验,但在不使用管理时,我使用 fields 属性做了类似的事情。然而在这种情况下,我得到一个异常,告诉 fields 不是表单的属性。 __dict__ 向我展示了一个 base_fields 属性,并且使用它是有效的。那么,为什么在这里使用 base_fields ,为什么 fields 不存在,最后我是在做一些黑客行为吗?

When creating a flatpage, I want the user to select a template from a predefined list. In order to keep the Flatpage model untouched, I prefer ChoiceField over ModelChoiceField (the latter provides the PK of the template, but I need the name for the template_name field):

class NewFlatpageForm(FlatpageForm):

    template_name = forms.ChoiceField(choices = [])
    def __init__(self, *args, **kwargs):
        self.base_fields['template_name'].choices = ProjectTemplate.objects.values_list('path', 'name')
        super(NewFlatpageForm, self).__init__(*args, **kwargs)

I override __init__ or Django populates choices at server start and does not update the list then.

I don't have any admin experience, but I did similar things using the fields attribute when not using admin. However in this case, I got an exception telling fields is not an attribute of the form. __dict__ showed me there's a base_fields attribute and using it works. So, why use base_fields here, and why is fields not present and finally am I doing something hacky?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

兔小萌 2024-08-25 20:43:43

在您调用 super之后之前,fields 并不存在。因此,只需交换行的顺序,使 super 排在第一位。

fields doesn't exist until after you've called super. So just swap the order of the lines, so that super comes first.

冷清清 2024-08-25 20:43:43

我自己的经验教训是:修改 base_fields 意味着您的修改将“永远”保留(直到 python 退出)。在您的情况下,这可能不是问题,因为您始终使用相同的字段名称,并且您将其值替换为 ProjectTemplate 中的分配...

在我的情况下,我想要基于构造函数中的参数完全不同的字段。由于我的字段名称通常不同,因此每次实例化表单时,我都会添加新字段,但不会删除上次的字段。

通过尽早调用 super (如此处所示),然后对 self.fields 而不是 self.base_fields 进行动态更改,我能够消除字段列表不断增长的问题。现在它完全有意义了,但我并不熟悉所有的语法细节,而是通过破解而不是首先尝试理解它。

A lesson from my own experience: modifying base_fields means that your modifications stick around "forever" (until python exits). In your case, that's probably not a problem, as you are always using the same field name, and you are replacing its values with the assignment from ProjectTemplate...

In my case, I wanted completely different fields based on parameters in the constructor. Since my field names were usually different, each time I instantiated a form, I added new fields but didn't eliminate the ones from the last time.

By calling super early (as indicated here) and then making my dynamic changes to self.fields instead of self.base_fields, I was able to eliminate the problem of an ever growing list of fields. It makes perfect sense now, but I wasn't familiar with all of the syntax details and was hacking through instead of trying to understand it first.

风吹过旳痕迹 2024-08-25 20:43:43

除了乔·杰姆斯卡。如果您确实需要根据请求更改表单,则可以使用深层复制来确保引用不会更改任何内容:

def get_form(self, request, obj=None, **kwargs):
    form = super(ResourceAdmin, self).get_form(request, obj, **kwargs)
    form = copy.deepcopy(form)

    if obj:
        form.base_fields['email'] = EmailField(initial=obj.user.email)
    if not request.user.is_superuser:
        form.base_fields['user'].widget = HiddenInput(attrs={'class': 'hide_form_row'})

    return form

In addition to Joe Germuska. If you truly need to change the form based on the request, you can use a deepcopy to make sure nothing is changed by reference:

def get_form(self, request, obj=None, **kwargs):
    form = super(ResourceAdmin, self).get_form(request, obj, **kwargs)
    form = copy.deepcopy(form)

    if obj:
        form.base_fields['email'] = EmailField(initial=obj.user.email)
    if not request.user.is_superuser:
        form.base_fields['user'].widget = HiddenInput(attrs={'class': 'hide_form_row'})

    return form
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文