Django, additional fields by product category

Please help. I'm trying to write an online store in Django. I want additional fields of product characteristics to appear depending on the product category. For example: if you select the "coffee" category in the admin panel when creating a product card, then a block with additional fields would appear: processing_method, geography, special, sour, roasting. If you select the category "tea" - there are other additional fields. I tried using fieldsets in admin.py - I realized that this option is not suitable. I stopped at creating a field in models.py - characteristics = models.JSONField(), read the documentation and did not understand how to implement my case. The meaning of the ideas is in the dynamic formation of the card (additional fields) when choosing a category I will be glad to any link with a similar example or a solution to a similar problem or guidance on the right way to solve this problem.


models.py

from django.db import models

class Category(models.Model):
name = models.CharField(max_length=100, db_index=True)
slug = models.SlugField(max_length=100, db_index=True, unique=True)

    class Meta:
        ordering = ('name',)
        verbose_name = 'category'
        verbose_name_plural = 'categories'
    
    def __str__(self):
        return self.name

class Product(models.Model):
ROASTING_CHOICES = (
(1, 1), (2, 2), (3, 3), (4, 4), (5, 5)
)
SOUR_CHOICES = (
('low', 'low'), ('medium', 'medium'), ('high', 'high')
)
VIEW_COFFEE_CHOICES = (
('arabica', 'arabica'), ('robusta', 'robusta'), ('arabica_blend', 'arabica_blend'),
('arabica_robusta', 'arabica_robusta')
)
VIEW_COFFEE_CHOICES = (
('popular', 'popular'), ('new_crop', 'new_crop'), ('your_choice', 'your_choice'),
('micro_lot', 'micro_lot'), ('sort_week', 'sort_week'), ('discounts', 'discounts'), ('new', 'new')
)
PROCESSING_METHOD_CHOICES = (
('dry', 'dry'), ('washed', 'washed'), ('other', 'other')
)
category = models.ForeignKey(Category, related_name='products', on_delete=models.CASCADE)
name = models.CharField(max_length=200, db_index=True)
slug = models.SlugField(max_length=200, db_index=True)
title = models.CharField(max_length=200, default='some_product')
image = models.ImageField(upload_to='products/%Y/%m/%d', blank=True)
description = models.TextField(blank=True)
characteristics = models.JSONField()
price = models.DecimalField(max_digits=10, decimal_places=2)
discount = models.DecimalField(max_digits=2, decimal_places=0, blank=True)
stock = models.PositiveIntegerField()
available = models.BooleanField(default=True)
created = models.DateTimeField(auto_now_add=True)
updated = models.DateTimeField(auto_now=True)

    class Meta:
        ordering = ('name', 'category')
        index_together = (('id', 'slug'),)
    
    def __str__(self):
        return self.name

==========================================================
Additional fields I'd like to add to the "coffee" category:


roasting = models.PositiveIntegerField(default=0, blank=True, choices=ROASTING_CHOICES)
sour = models.CharField(max_length=30, blank=True, choices=SOUR_CHOICES)
view = models.CharField(max_length=30, blank=True, choices=VIEW_COFFEE_CHOICES)
special = models.CharField(max_length=30, blank=True, choices=VIEW_COFFEE_CHOICES)
processing_method = models.CharField(max_length=30, blank=True, choices=VIEW_COFFEE_CHOICES)
geography = models.CharField(max_length=50, blank=True)

===========================================================


admin.py

from django.contrib import admin
from .models import Category, Product

class CategoryAdmin(admin.ModelAdmin):
list_display = ['name', 'slug']
prepopulated_fields = {'slug': ('name',)}

admin.site.register(Category, CategoryAdmin)

class ProductAdmin(admin.ModelAdmin):
search_fields = ("name__startswith",)
list_display = ['name', 'slug', 'category', 'price', 'stock', 'available', 'created', 'updated']
list_filter = ['category', 'available', 'created', 'updated']
list_editable = ['price', 'stock', 'available']
prepopulated_fields = {'slug': ('name',)}

admin.site.register(Product, ProductAdmin)
Back to Top