开发者

How can I set arbitrary attributes on Django Model Fields, then access them in a ModelForm?

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 runn开发者_JAVA技巧ing 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?


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


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 }}.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜