在Django管理站点中使用动态创建的类别作为模型,并多次注册模型

时间:2015-09-11 22:20:32

标签: python django django-models django-admin

我在Django管理员中配置以下设置时遇到了一些问题。

设定:

假设我有以下Django模型:

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

然后是另一个模型,它允许最终用户为部分提供自定义名称并为该部分分配适当的模型:

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)

用户在数据库中定义以下自定义部分:

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

目前:

在管理员中,我们得到以下内容:

Foods
Meats
Fruits
Sections

管理员允许我们添加肉或水果并将其分配到自定义部分,但这需要数据输入人员知道橙子是水果还是肉。我只是不愿意把它留给机会,你知道......

例如,当前的操作顺序是:

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

我想做什么:

我希望管理员列出自定义栏目名称,以便用户可以选择将项目添加到其中一个用户创建的栏目中:

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

现在,当用户选择通过管理员向数据库添加橙色时,将提供水果形式,有机牛肉将提供肉形式。所以操作的顺序是:

admin -> add Orange -> Name it Blood Orange

我当然可以为此编写一个自定义界面,但我希望这可以在django管理界面中轻松实现?

1 个答案:

答案 0 :(得分:0)

感谢proxy classes我能够轻松获得我想要的确切结果(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)

基本上为每个部分动态创建适当模型的代理类。在该部分后面命名。然后为每个部分创建一个admin.ModelAdmin类。最后注册管理员。简单!

我会在接受这个答案之前等待一个星期左右,以防任何人有更好的方法或看到任何潜在的问题。

已经差不多一个月所以我想这就是它..