如何在 Django 模型字段上设置任意属性,然后在 ModelForm 中访问它们?

发布于 2024-09-26 23:38:59 字数 1563 浏览 4 评论 0原文

Django 的作用

Django 的模型字段“空白”属性,以及当您创建 ModelForm 时它被否定并转变为表单字段“必需”属性的方式,非常酷。它允许我在其所属的模型上设置属性,但在处理从它创建的 ModelForm 时可以使用“required”属性。在模板中渲染时提供“必需”意味着我可以做一些很酷的事情,例如向必填字段的显示标签添加星号。

模型

class Employee(models.Model):
    name = models.CharField(blank=False)
    public_bio = models.TextField(blank=False)
    salary= models.DecimalField(max_digits=15, decimal_places=2, blank=False)
    personnel_notes = models.TextField(blank=True)

模板(使用 ModelForm)

{% for field in form %}
    <p>
       {{ field.label }}{% if field.required %}*{% endif %}
       {{ field }}
    </p>
{% endfor %}

我希望它做什么

但如果我想用我自己的新属性来做到这一点该怎么办?它不需要以空白的方式否定/翻译 --> required 确实如此,但我希望在模型字段上定义的新属性可以在我的表单字段上访问。例如,假设我想向用户明确说明可能发布哪些字段:

模型

class Employee(models.Model):
    name = models.CharField(blank=False, publishable=True)
    public_bio = models.TextField(blank=False, publishable=True)
    salary= models.DecimalField(max_digits=15, decimal_places=2, blank=False, publishable=False)
    personnel_notes = models.TextField(blank=True, publishable=False)

模板(使用 ModelForm)

{% for field in form %}
    <p>
       {{ field.label }}{% if field.required %}*{% endif %}
       {% if field.publishable %}(may be published){% endif %}
       {{ field }}
    </p>
{% endfor %}

有什么方法可以做到这一点吗?尝试一下,我立即遇到了模型定义的问题,其中 django.db.models.fields.Field.__init__() 甚至不接受 kwargs。如果这是不可能的,有什么解决方法来获得所需行为的想法吗?

What Django Does

Django's Model Field "blank" attribute, and the way it gets negated and turned into the Form Field "required" attribute when you create a ModelForm, is pretty cool. It allows me to set the property on the model where it belongs, but have the "required" attribute available when handling a ModelForm created from it. Having "required" available when rendering in a template means I can do cool things like add an asterisk to the display labels of required fields.

Model

class Employee(models.Model):
    name = models.CharField(blank=False)
    public_bio = models.TextField(blank=False)
    salary= models.DecimalField(max_digits=15, decimal_places=2, blank=False)
    personnel_notes = models.TextField(blank=True)

Template (using ModelForm)

{% for field in form %}
    <p>
       {{ field.label }}{% if field.required %}*{% endif %}
       {{ field }}
    </p>
{% endfor %}

What I Want It to Do

But what if I want to do that with my own, new attribute? It doesn't need to be negated/translated the way blank --> required does, but I want my new attribute, defined on the Model Field, to be accessible on my FormFields. For example, let's say I want to make explicit to the user which fields might be published:

Model

class Employee(models.Model):
    name = models.CharField(blank=False, publishable=True)
    public_bio = models.TextField(blank=False, publishable=True)
    salary= models.DecimalField(max_digits=15, decimal_places=2, blank=False, publishable=False)
    personnel_notes = models.TextField(blank=True, publishable=False)

Template (using ModelForm)

{% for field in form %}
    <p>
       {{ field.label }}{% if field.required %}*{% endif %}
       {% if field.publishable %}(may be published){% endif %}
       {{ field }}
    </p>
{% endfor %}

Is there any way to do this? Trying it, I'm running into an issue immediately with the model definition, where django.db.models.fields.Field.__init__() doesn't even accept kwargs. If this isn't possible, any ideas for workarounds to get the desired behavior?

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

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

发布评论

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

评论(2

梦途 2024-10-03 23:38:59

请注意,publishable 应该是 forms.Field 上的属性,而不是 models.Field 上的属性,以便它将出现在模板中。

您可以将其显式添加到您希望在表单启动时可发布的字段上,并且在渲染时可以使用它:

class PublishableForm(forms.Form):
    name = forms.CharField()

    def __init__(*args, **kwargs)
       super(PublishableForm, self).__init__(*args, **kwargs)
       self.name.publishable = True

Note that publishable should be a property on the forms.Field, not on the models.Field, so that it will appear in the template.

You can add this explicitly on the fields you wish to have publishable in the form's initiation, and it will be available to you while rendering:

class PublishableForm(forms.Form):
    name = forms.CharField()

    def __init__(*args, **kwargs)
       super(PublishableForm, self).__init__(*args, **kwargs)
       self.name.publishable = True
只为守护你 2024-10-03 23:38:59

您还可以为模型字段创建一种装饰器:

def publishable(field):
    field.publishable = True
    return field

#...

name = publishable(models.CharField(...))

然后覆盖表单的 __init__ 以使用这些字段。

另外不要忘记在模板中使用 {{ form.name }} 返回 BoundField。要获取原始表单字段,您应该使用 {{ form.name.field }}

You can also make kind of decorator for model fields:

def publishable(field):
    field.publishable = True
    return field

#...

name = publishable(models.CharField(...))

Then override form's __init__ to use these fields.

Also don't forget that using {{ form.name }} in template returns BoundField. To get original form field you should use {{ form.name.field }}.

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