Search code examples
python-3.xdjangodjango-modelsdjango-formsdjango-admin

Django Admin Tabural Inline Throwing Error


I have created a Category and Product model when In the product model I have created a category field which is foreign key relation to the category model.

class Category(models.Model):
name = models.CharField(max_length=100)
icon= models.ImageField(upload_to='CategoryIcons/', blank=True, null=True)
created_at = models.DateTimeField(auto_now_add=True)

def __str__(self):
    return self.name

Here is the Product Model -

class Product(models.Model):
title = models.CharField(max_length=200)
category = models.ForeignKey(Category, on_delete=models.CASCADE, related_name='products')
productImages = models.ManyToManyField(ProductImages)
price = models.IntegerField()
qty = models.IntegerField(default=0)
shortDescription = models.TextField(blank=True, null=True)
active = models.BooleanField(default=True)
created_at = models.DateTimeField(auto_now_add=True)

def __str__(self):
    return f'{self.title}{ self.category}'

Now when I try to use Django tabural Inline class with it says SystemCheckError: System check identified some issues:

ERRORS: <class 'shop.admin.CategoryInline'>: (admin.E202) 'shop.Category' has no ForeignKey to 'shop.Product'.

admin.py file code -

    from django.contrib import admin
from .models import Category, ProductImages, Product, Order, Shipping, OrderItem

# Register your models here.

class CategoryInline(admin.TabularInline):
    model = Category
    readonly_fields = ('id', 'created_at')
    extra = 2


class ProductAdmin(admin.ModelAdmin):
    inlines = [ CategoryInline, ]
    
admin.site.register(Category)
admin.site.register(ProductImages )
admin.site.register(Product, ProductAdmin)
admin.site.register(Order)
admin.site.register(Shipping)
admin.site.register(OrderItem)

I am confused that where I am doing wrong as in most of the places I see the same formate and code. Please help me out.


Solution

  • As Category is a ForeignKey to Product, not the other way around, that is why you are getting the error. Instead, you can show the products inside the Category Adminsite, like this:

    class ProductInline(admin.TabularInline):
        model = Product
        readonly_fields = ('id', 'created_at')
        extra = 2
    
    
    class CategoryAdmin(admin.ModelAdmin):
        inlines = [ ProductInline, ]
        
    admin.site.register(Category, CategoryAdmin)
    

    Or, you can define the relation between Product to Category as ManyToMany, then the inline functionality should work. In that case the implementation should be like this:

    #model
    class Product(models.Model):
        categories = models.ManyToManyField(Category)
    
    #admin
    
    from django.contrib import admin
    
    class CategoryInline(admin.TabularInline):
        model = Product.categories.through
    
    class ProductAdmin(admin.ModelAdmin):
        inlines = [
            CategoryInline,
        ]
    

    ManyToMany relation sounds more logical because one product can have multiple categories, similarly one category can have multiple products. More information can be found regarding admin site implementation in the documentation.