Inside my django admin, I am creating an admin model that has a one to many relationship with another table. Let us call it Recipes
and Ingredients
. Each recipe has multiple ingredients.
I want to make it so in the admin page a user can create a recipe and add certain ingredients to it on the same page. So I am using the concept of inline models
. The issue is that once certain ingredients have been created only a few fields should be allowed to be edited. So I've created two separate inline models -- one for editing and one for adding.
The other issue is that ingredient creation can only be done if the user has certain permissions. If the user does not have those permissions it still creates the ingredients but they are not published
. They later have to get approved by someone with the correct permissions. Right now I am overriding the formset
for the creating of the ingredient. It looks like this:
class AddIngredientInlineFormset(forms.models.BaseInlineFormSet):
model = Ingredient
def save(self, commit=True):
can_publish = self.request.user.has_perm('meals.publish_ingredient')
for form in self.forms:
if form.cleaned_data:
Ingredient.objects.create(
is_published = can_publish, **kwargs
)
class AddIngredientInline(admin.StackedInline):
model = Ingredient
formset = AddIngredientInlineFormset
fields = ['name', 'amount', 'description']
extra = 1
def has_change_permission(self, request):
return False
Then I have a separate inline class for editing:
class EditIngredientInline(admin.StackedInline):
model = Ingredient
fields = ['name', 'amount', 'description']
readonly_fields = ['name', 'amount']
extra = 0
can_delete = False
def has_add_permission(self, request):
return False
Then in my recipe admin model, it looks like this:
class RecipeAdmin(BaseModelAdmin):
model = models.Recipe
list_display = ['name']
def add_view(self, request, form_url='', extra_context={}):
self.inlines = [AddIngredientInline]
return super(BaseModelAdmin, self).add_view(request, form_url, extra_context)
def change_view(self, request, object_id, form_url='', extra_context={}):
self.inlines = [EditIngredientInline, AddIngredientInline]
return super(BaseModelAdmin, self).change_view(request, object_id, form_url, extra_context)
This works fine for adding recipes and ingredients for those recipes, and the display shows up fine for everything. However when I try to edit an existing ingredient for a given recipe I get the error: IngredientFormFormSet' object has no attribute 'new_objects'
I imagine this is happening because I am not using formset.save()
for the AddIngredientFormSet
. Also this has begun to get fairly complicated, so I am wondering if there is a better way to check the permissions for publishing the inline ingredient and save that column correctly.