Multi-table inheritance and two many to many via through model not working in admin inline

35 Views Asked by At

I'm trying to create navigation menu from the django admin as per user's requirement. The Model look like this:

class MenuItem(models.Model):
    title = models.CharField(max_length=200, help_text='Title of the item')
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)
    is_published = models.BooleanField(default=False)

    def __str__(self):
        return self.title


class Page(MenuItem):
    """
    To display non-hierarchical pages such as about us, or some page in menu
    """
    slug = models.SlugField(max_length=200, unique=True, help_text='End of url')
    content = HTMLField(help_text='Contents of the page')
    author = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.DO_NOTHING)


class Category(MenuItem):
    """
    For hierarchical display eg. in navigation menu use Category and Articles.
    """
    slug = models.SlugField(max_length=200, unique=True, help_text='End of url')

    class Meta:
        verbose_name_plural = 'categories'

Page and Category can be different types of menu items, so, I used inheritance. Now I want to bind the MenuItem to a Menu, hence I added two more models below.

class Menu(models.Model):
    title = models.CharField(max_length=200, unique=True, help_text='Name of the menu.')
    is_published = models.BooleanField(default=False)
    item = models.ManyToManyField(MenuItem, through='MenuLevel', through_fields=['menu', 'menu_item'])

    def __str__(self):
        return self.title


class MenuLevel(models.Model):
    menu = models.ForeignKey(Menu, on_delete=models.CASCADE)
    menu_item = models.ForeignKey(MenuItem, on_delete=models.CASCADE, related_name='items')
    level = models.IntegerField(default=0)
    parent = models.ForeignKey(MenuItem, on_delete=models.CASCADE, related_name='parent', null=True, blank=True)

I need the parent key to menu item to traverse through the menu items from parent to children and level to sort the menu in order.

On the admin I have two simple classes:

class MenuLevelInline(admin.TabularInline):
    model = MenuLevel

@admin.register(Menu)
class MenuAdmin(admin.ModelAdmin):
    inlines = [MenuLevelInline]

Here is the problem: If I try to save two categories, one as a parent to another, things work fine. However, if I have a category as a parent and Page as a child I get IntegrityError: FOREIGN KEY constraint failed error.

When I look in the database, the menu_item table does contain all the keys for both Categories and pages table.

What did I do wrong?

1

There are 1 best solutions below

0
On

Everything just worked once I switched to MySQL. It was not working on Sqlite. I don't know why it doesn't work with sqlite maybe it is a bug. But changing the database solved my problem.