How to set custom attributes in Django Model Fields and then get them in ModelForm?

What does Django do

Django Model Field is an “empty” attribute, and the way it is reset and turned into the “Required form field attribute” attribute when creating a ModelForm is pretty cool. It allows me to set a property on the model where it belongs, but it has a “required” attribute, available when working with ModelForm created from it. Having the "necessary" available when rendering in the template, I can do cool things, for example, add an asterisk to the shortcuts for displaying the 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 to do

But what if I want to do this with my own, new attribute? It does not need to be denied / translated blank → required, but I want my new attribute defined in the model field to be available on my FormFields. For example, suppose I want to tell the user which fields can 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, I immediately run into the problem of defining a model where django.db.models.fields.Field.__init__() doesn't even accept kwargs. If this is not possible, any workaround ideas to get the desired behavior?

+4
source share
2 answers

Note that posting must be a property in forms. Field, not on models. Field so that it appears in the template.

You can add this explicitly to the fields that you want to publish at the beginning of the form, and will be available to you when rendering:

 class PublishableForm(forms.Form): name = forms.CharField() def __init__(*args, **kwargs) super(PublishableForm, self).__init__(*args, **kwargs) self.name.publishable = True 
+1
source

You can also make a decorator for model fields:

 def publishable(field): field.publishable = True return field #... name = publishable(models.CharField(...)) 

Then override the __init__ form to use these fields.

Also, remember that using {{ form.name }} in the template returns a BoundField. To get the original form field, you must use {{ form.name.field }} .

0
source

All Articles