Oscar Mederos
Oscar Mederos

Reputation: 29823

Force the user to add an instance of some InlineModelAdmin when adding a model

I have a UserAdmin, and I defined a UserProfileInline like this:

from ...  
from django.contrib.auth.admin import UserAdmin as UserAdmin_

class UserProfileInLine(admin.StackedInline):
    model = UserProfile
    max_num = 1
    can_delete = False
    verbose_name = 'Profile'
    verbose_name_plural = 'Profile'

class UserAdmin(UserAdmin_):
    inlines = [UserProfileInLine]

My UserProfile model has some required fields.

What I want is to force the user not only to enter the username & repeat password, but also to enter at least the required fields so that the UserProfile instance is created and associated to the User that is being added.

If I enter anything in any field of UserProfileInline when creating the user, it validates the form without problem, but if I don't touch any field, it just creates the User and nothing happens with the UserProfile.

Any thoughts?

Upvotes: 0

Views: 360

Answers (1)

okm
okm

Reputation: 23871

Check recent answer Extending the user profile in Django. Admin creation of users , you need to set the empty_permitted attribute of the form of the inline , to be False. Just like

class UserProfileForm(forms.ModelForm):
    def __init__(self, *args, **kwargs):
        super(UserProfileForm, self).__init__(*args, **kwargs)
        if self.instance.pk is None:
            self.empty_permitted = False # Here

    class Meta:
        model = UserProfile


class UserProfileInline(admin.StackedInline):                                     
    form = UserProfileForm  

Another possible solution could be to create your own Formset (that inherits from BaseInlineFormSet), like suggested in this link.

It could be something like that:

class UserProfileFormset(BaseInlineFormSet):
    def clean(self):
        for error in self.errors:
            if error:
                return
        completed = 0
        for cleaned_data in self.cleaned_data:
            # form has data and we aren't deleting it.
            if cleaned_data and not cleaned_data.get('DELETE', False):
                completed += 1

        if completed < 1:
            raise forms.ValidationError('You must create a User Profile.')

Then specify that formset in the InlineModelAdmin:

class UserProfileInline(admin.StackedInline):
    formset = UserProfileFormset
    ....

The good thing about this second option is that if the UserProfile model doesn't require any field to be filled, it will still ask for you to enter any data in at least one field. The first mode doesn't.

Upvotes: 1

Related Questions