How do I require an inline in the Django Admin?

django admin inline
django admin template
django admin many to-many
django admin permissions
django admin dashboard
django admin custom field
django admin custom form
django admin inline foreign key

I have the following admin setup so that I can add/edit a user and their profile at the same time.

class ProfileInline(admin.StackedInline):
    """
    Allows profile to be added when creating user
    """
    model = Profile


class UserProfileAdmin(admin.ModelAdmin):
    """
    Options for the admin interface
    """
    inlines = [ProfileInline]
    list_display = ['edit_obj', 'name', 'username', 'email', 'is_active',
        'last_login', 'delete_obj']
    list_display_links = ['username']
    list_filter = ['is_active']
    fieldsets = (
        (None, {
            'fields': ('first_name', 'last_name', 'email', 'username',
                'is_active', 'is_superuser')}),
        )
    ordering = ['last_name', 'first_name']
    search_fields = ['first_name', 'last_name']

admin.site.register(User, UserProfileAdmin)

The problem is I need two of the fields in the Profile inline form to be required when adding the user. The inline form doesn't validate unless input is entered. Is there anyway to make the inline required, so that it can't be left blank?

I took Carl's advice and made a much better implementation then the hack-ish one I mentioned in my comment to his answer. Here is my solution:

From my forms.py:

from django.forms.models import BaseInlineFormSet


class RequiredInlineFormSet(BaseInlineFormSet):
    """
    Generates an inline formset that is required
    """

    def _construct_form(self, i, **kwargs):
        """
        Override the method to change the form attribute empty_permitted
        """
        form = super(RequiredInlineFormSet, self)._construct_form(i, **kwargs)
        form.empty_permitted = False
        return form

And the admin.py

class ProfileInline(admin.StackedInline):
    """
    Allows profile to be added when creating user
    """
    model = Profile
    extra = 1
    max_num = 1
    formset = RequiredInlineFormSet


class UserProfileAdmin(admin.ModelAdmin):
    """
    Options for the admin interface
    """
    inlines = [ProfileInline]
    list_display = ['edit_obj', 'name', 'username', 'email', 'is_active',
        'last_login', 'delete_obj']
    list_display_links = ['username']
    list_filter = ['is_active']
    fieldsets = (
        (None, {
            'fields': ('first_name', 'last_name', 'email', 'username',
                'is_active', 'is_superuser')}),
        (('Groups'), {'fields': ('groups', )}),
    )
    ordering = ['last_name', 'first_name']
    search_fields = ['first_name', 'last_name']


admin.site.register(User, UserProfileAdmin)

This does exactly what I want, it makes the Profile inline formset validate. So since there are required fields in the profile form it will validate and fail if the required information isn't entered on the inline form.

#15174 (Add a required inline on django admin) – Django, If the user provides data for the UserProfile, it will be validated and saved. However, an empty form also passes validation -- there's no easy way to require that the  GenericStackedInline is an inline model admin, that uses GenericForeignKey, Django AdminLog model however only uses object_id and content_type but does not define actual GenericForeignKey field. However GenericStackedInline does not require actual GenericForeignKey as it directly uses object_id and content_type .

Now with Django 1.7 you can use parameter min_num. You do not need class RequiredInlineFormSet anymore.

See https://docs.djangoproject.com/en/1.8/ref/contrib/admin/#django.contrib.admin.InlineModelAdmin.min_num

class ProfileInline(admin.StackedInline):
    """
    Allows profile to be added when creating user
    """
    model = Profile
    extra = 1
    max_num = 1
    min_num = 1 # new in Django 1.7


class UserProfileAdmin(admin.ModelAdmin):
    """
    Options for the admin interface
    """
    inlines = [ProfileInline]
    ...


admin.site.register(User, UserProfileAdmin)

Django Tutorial Part 4: Django admin site, has a signal for when an app is loaded. The Django admin site¶ One of the most powerful parts of Django is the automatic admin interface. It reads metadata from your models to provide a quick, model-centric interface where trusted users can manage content on your site. The admin’s recommended use is limited to an organization’s internal management tool.

You can probably do this, but you'll have to get your hands dirty in the formset/inline code.

First of all, I think you want there to be always one form in the formset in this case, and never more than one, so you'll want to set max_num=1 and extra=1 in your ProfileInline.

Your core problem is that BaseFormSet._construct_form passes empty_permitted=True to each "extra" (i.e. empty) form in the formset. This parameter tells the form to bypass validation if its unchanged. You just need to find a way to set empty_permitted=False for the form.

You can use your own BaseInlineFormset subclass in your inline, so that might help. Noticing that _construct_form takes **kwargs and allows that to override the kwargs passed to the individual Form instances, you could override _construct_forms in your Formset subclass and have it pass empty_permitted=False in every call to _construct_form. The downside there is that you're relying on internal APIs (and you'd have to rewrite _construct_forms).

Alternatively, you could try overriding the get_formset method on your ProfileInline, and after calling the parent's get_formset, manually poke at the form inside the returned formset:

def get_formset(self, request, obj=None, **kwargs):
    formset = super(ProfileInline, self).get_formset(request, obj, **kwargs)
    formset.forms[0].empty_permitted = False
    return formset

Play around and see what you can make work!

Django under the hood: how the Django admin works, installation inside your operating system's or virtual env Python environment (e.g. <virtual_env_directory>/lib/python3. How do I add a custom inline admin widget in Django? Home. Since Django 1.1, formfield_overrides is also working All you Need to Know About Implements In Java

The easiest and most natural way to do that is via fomset clean():

class RequireOneFormSet(forms.models.BaseInlineFormSet):
    def clean(self):
        super().clean()
        if not self.is_valid():
            return
        if not self.forms or not self.forms[0].cleaned_data:
            raise ValidationError('At least one {} required'
                                  .format(self.model._meta.verbose_name))

class ProfileInline(admin.StackedInline):
    model = Profile
    formset =  RequireOneFormSet

(Inspired by this Matthew Flanagan's snippet and Mitar's comment below, tested to work in Django 1.11 and 2.0).

Django admin custom page layout, data & behaviors, TabularInline): model = GosExamMark extra = 1 class StudentOptions(admin. trough admin site i got error in extra object form that tells me fields are required. 1. How to edit mutiple models from one Django admin? 2. How to add One to One relation as admin inline? 3. How to add nested inlines in Django admin? 4. How to create a single Django admin from two different models? 1. How to show larger number of rows on listview page? 2. How to disable django admin pagination? 3. How to add date based

You need to set min_num in inline and validate_min in formset.

https://docs.djangoproject.com/en/1.8/topics/forms/formsets/#validate-min

class SomeInline(admin.TabularInline):
    ...
    min_num = 1

    def get_formset(self, request, obj=None, **kwargs):
        formset = super().get_formset(request, obj=None, **kwargs)
        formset.validate_min = True
        return formset

The Django admin site | Django documentation, en/1.5/ref/contrib/admin) should mention something specific about inline form to (​https://docs.djangoproject.com/en/dev/ref/contrib/admin/#django.contrib.​admin. However, if I specify the form, but not the model, I get a 'model' is required  In order to create the inline forms, we will use Django’s inline form sets. These kind of form sets allows you to create several child objects from a parent object, all in the same form. These are the base of what Django admin uses when you register inlines instances. For our example, we are going to go further and be even more abstract.

#5954 (inline extra fields are required) – Django, Customize Save In Django Admin Inline Form As a CMS, we are also required to provide a feature to create Author and several Books for him together. So, the  Set show_change_link to True (False by default) in your inline model, so that inline objects have a link to their change form (where they can have their own inlines). from django.contrib import admin class PostInline(admin.StackedInline): model = Post show_change_link = True

#20023 (Admin Inline form validation must go in Model.clean() if , OneToOneFields can be set as inlines in the same way as a FK. However, only one side of the OneToOneField can be set as the inline model. You have a  In the Post/Author example you provided, using inlines would mean that the page for editing Posts would also display an inline form for adding/editing/removing Authors. Much more natural to the end user. What you can do in your admin list view is create a callable in the Post model that will render a comma separated list of Authors.

How to customize save in django admin inline form? · GitHub, from django.contrib import admin from news.models import News from Checks if the original field was required and if so makes the default translation field required instead. A translated inline must derive from one of the following classes:. class CertificateInline(admin.StackedInline): model = Certificate class PersonAdmin(admin.ModelAdmin): inlines = [CertificateInline,] admin.site.register(Person,PersonAdmin) but i need to include the Training_Date model as inline which is part of Certificate admin inline.

Comments
  • If you are using GenericInlineModelAdmin, replace BaseInlineFormSet with BaseGenericInlineFormSet.
  • Thanks! However, if your form does not have required fields, it will still not validate and save when empty. Monkey-patch the form using form.has_changed = lambda: True to have it saved despite being empty.
  • This only controls the number of inlines that are shown. It doesn't require that any are filled in.
  • Actually if inline has one of the field required, it also control that inline itself is filled in.
  • Testing in 1.10, even with "min_num" set still allows users to select "Delete" on all records, leaving you with no records.
  • Thanks for the information. I did come up with a solution but it is very hack-ish, and I'm not particularly proud of it. I ended up overrideing the add_view for the ModelAdmin and copying all of the code from the default view and modifying the formset values. I'm going to take a look at your suggestions to see if I can implement it in a cleaner way. Thanks for the leads!
  • Perfect! I changed it a bit, used if not self.is_valid(): instead of manually going through self.errors and used self.model._meta.verbose_name.
  • Why isn't this the most voted and accepted answer? This is a highly clean solution, Only thing I would ask is how do I customize the validation error it reads: Please submit {min_num} or more forms.