Question

I came across this code:

drinker/models.py:

from django.db import models
from django.db.models.signals import post_save
from django.contrib.auth.models import User

class Drinker(models.Model):
        user            = models.OneToOneField(User)
        birthday        = models.DateField()
        name            = models.CharField(max_length=100)

        def __unicode__(self):
                return self.name

drinker/forms.py:

from django import forms
from django.contrib.auth.models import User
from django.forms import ModelForm
from drinker.models import Drinker

class RegistrationForm(ModelForm):
        username        = forms.CharField(label=(u'User Name'))
        email           = forms.EmailField(label=(u'Email Address'))
        password        = forms.CharField(label=(u'Password'), widget=forms.PasswordInput(render_value=False))
        password1       = forms.CharField(label=(u'Verify Password'), widget=forms.PasswordInput(render_value=False))

        class Meta:
                model = Drinker
                exclude = ('user',)

        def clean_username(self):
                username = self.cleaned_data['username']
                try:
                        User.objects.get(username=username)
                except User.DoesNotExist:
                        return username
                raise forms.ValidationError("That username is already taken, please select another.")

        def clean(self):
                if self.cleaned_data['password'] != self.cleaned_data['password1']:
                        raise forms.ValidationError("The passwords did not match.  Please try again.")
                return self.cleaned_data

My Question is about the inner class meta which as two attributes:

model=Drinker
exclude=('user`,)

I have a not-so-clear understanding of how this meta class work. I have read the documentation but I am still confused. Can you kindly explain what those two lines mean and what their purpose is? Thanks

Was it helpful?

Solution

The exclude attribute tells Django what fields from the model not to include in the form.

Quoting the Selecting fields to use section of the model form documentation:

2. Set the exclude attribute of the ModelForm’s inner Meta class to a list of fields to be excluded from the form.

The model line simply tells Django what model to take the fields from; together the two lines tell Django to give RegistrationForm fields based on all fields on the Drinker model, except 'user'. For the given Drinker model, that's birthday and name.

These fields are added to the other form fields already defined on the form. If the Drinker model gained more fields, those would automatically be part of the form too.

See the Overriding the default fields section of the same chapter:

When you explicitly instantiate a form field like this, it is important to understand how ModelForm and regular Form are related.

ModelForm is a regular Form which can automatically generate certain fields. The fields that are automatically generated depend on the content of the Meta class and on which fields have already been defined declaratively. Basically, ModelForm will only generate fields that are missing from the form, or in other words, fields that weren’t defined declaratively.

The inner Meta class is just a convenient way to create a namespace for such configuration on your form class for the Django framework to find. All Django now has to do is introspect Form.Meta and see what attributes are defined there.

Note that using exclude can lead to security problems. From the same documenation:

It is strongly recommended that you explicitly set all fields that should be edited in the form using the fields attribute. Failure to do so can easily lead to security problems when a form unexpectedly allows a user to set certain fields, especially when new fields are added to a model. Depending on how the form is rendered, the problem may not even be visible on the web page.

The alternative approach would be to include all fields automatically, or blacklist only some. This fundamental approach is known to be much less secure and has led to serious exploits on major websites (e.g. GitHub).

OTHER TIPS

fields = exclude() and fields = '__all__' - means display all the fields

exclude = ('password',) - means exclude password field

fields = ('user','email',) - means display only email field and userfield

in short : fields you want to show up in the form should be mentioned in 'fields' attribute ex:

fields = '__all__'  #will show all the fields from the model in the form

'exclude' does the opposite

 exclude = ['title'] # don't show the title field
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top