0

I'm having some issues configuring the following setup in the Django admin.

Setup:

Lets say i have the following Django models:

class Food(models.Model):
    section = models.ManyToManyField(Section, related_name='foods')
class Fruit(Food):
    pass
class Meat(Food):
    pass

Then another model which allows the end user to give custom names to sections and assign the appropriate model to that section:

class Section(models.Model):
    FOOD = 'FO'
    FRUIT = 'FR'
    MEAT = 'ME'
    MODEL_CHOICES = (
        (FOOD, 'Food'),
        (FRUIT, 'Fruit'),
        (MEAT, 'Meat'),
    )
    name = models.CharField(max_length=20)
    model = models.CharField(max_length=2,
                             choices=MODEL_CHOICES,
                             default=FIELDS)

The user defines the following custom sections in the database:

name = Oranges          model = Fruit
name = Apples & Pears   model = Fruit
name = Organic beef     model = Meat
name = Regular beef     model = Meat

Currently:

In the admin we get the following:

Foods
Meats
Fruits
Sections

The admin allows us to add a meat or a fruit and assign it to a custom section, but this would require the data entry person to know if Oranges are a fruit or a meat. I'm just not willing to leave that to chance, ya know..

For example the current order of operations is this:

admin -> add Fruit item -> Name it Blood Orange & assign it to the Oranges section

What i would like to do:

I would like the admin to list the custom section names so that the user can choose to add an item to one of these user created sections:

Oranges (user defined)
Apples & Pears (user defined)
Organic beef (user defined)
Regular beef (user defined)
Sections

Now, when the user chooses to add an orange to the database via admin the fruit form would be supplied and Organic beef would supply the meat form. So the order of operations to be:

admin -> add Orange -> Name it Blood Orange

I can certainly write a custom interface for this, but i was hoping that this could easily implemented in the django admin interface?

Zulu
  • 8,765
  • 9
  • 49
  • 56
Arctelix
  • 4,478
  • 3
  • 27
  • 38
  • could you be more clear, or precise, or more elaborate with your required output? I think what you wish could be done via dynamically creating admin classes, with a base class inherited for common attributes, and some fields based on values pulled from models – coolharsh55 Sep 12 '15 at 05:30
  • @kicker86 See revised question above. I hope that helps to clarify. Let me know if you have specific questions. – Arctelix Sep 12 '15 at 14:57

1 Answers1

0

Thanks to proxy classes i was able to get the exact results i was looking for quite easily (admin.py):

def create_proxy_admin(model_admin, model, name = None):
    # Create a proxy class for the specified model
    class  Meta:
        proxy = True
        app_label = model._meta.app_label

    attrs = {'__module__': '', 'Meta': Meta}
    proxy_model = type(name, (model,), attrs)

    # Register the proxy model with model_admin
    admin.site.register(proxy_model, model_admin)

for section in Section.objects.all():
    name = str(section.name.capitalize())

    # Define any attributes for the admin
    # Could be modified for each section as required!
    admin_attrs = {'list_display': ('some_field', ), 
                  }

    # Select the appropriate model
    if section.model == section.FRUIT:
        Model = Fruit
    elif section.model == section.MEAT:
        Model = Meat
    else:
        Model = Food

    # Create ModelAdmin class
    Admin = type(name+'Admin', (admin.ModelAdmin,), admin_attrs)

    # Create proxy model and register with admin
    create_proxy_admin(Admin, name=name, model=Model)

Basically for each section, dynamically create a proxy class for the appropriate model. Name it after the section. Then create an admin.ModelAdmin class for each section. Finally register both with the admin. Easy!

I will wait a week or so before accepting this answer just in case anybody has a better way or sees any potential issues.

It's been almost a month so i guess this is it..

Community
  • 1
  • 1
Arctelix
  • 4,478
  • 3
  • 27
  • 38