在django admin中表示多对多关系的更好方式

时间:2010-02-25 07:00:35

标签: python django django-models django-admin

我有一个独特的问题,应该在django admin中处理它。

我有以下模型结构......

class Product(models.Model):
    name    = models.CharField(max_length = 100)
    base_price = models.DecimalField(max_digits = 5, decimal_places = 2)


    def __unicode__(self):
        return self.name


class Country(models.Model):
    name = models.CharField(max_length = 2)
    base_price = models.DecimalField(max_digits = 5, decimal_places = 2)    

    def __unicode__(self):
        return self.name


class CountryProduct(models.Model):
    country = models.ForeignKey(Country)
    product = models.ForeignKey(Product)
    overriden_price = models.DecimalField(max_digits = 5, decimal_places = 2)

    class Meta:
        unique_together = (("country", "product"),)

如图所示,产品与国家之间存在多种关系....我想提供管理界面以覆盖特定国家和产品的基本价格。

ui的一个选项如下,此处短划线( - )表示默认价格,数字值表示给定国家/地区和产品的覆盖价格。

countries -> | US  | UK 
products     |     |
---------------------------
Product1     |  -  |  10
Product2     |  5  |   7

但我不知道该怎么做....

我愿意看看替代方法(包括模型结构的变化)以及满足要求......任何形式的输入肯定对我有用......

提前致谢:)

3 个答案:

答案 0 :(得分:2)

我得到了解决方案,这是我对我的问题的回答......让我与你分享......我按照以下方式更改了模型....

class Product(models.Model):
    name    = models.CharField(max_length = 100)
    base_price = models.DecimalField(max_digits = 5, decimal_places = 2)


    def __unicode__(self):
        return self.name


class Country(models.Model):
    name = models.CharField(max_length = 2)
    base_price = models.DecimalField(max_digits = 5, decimal_places = 2)    
    products = models.ManyToManyField(Product, through = 'CountryProduct')

    def __unicode__(self):
        return self.name


class CountryProduct(models.Model):
    country = models.ForeignKey(Country)
    product = models.ForeignKey(Product)
    overriden_price = models.DecimalField(max_digits = 5, decimal_places = 2)

    class Meta:
        unique_together = (("country", "product"),)


class CountryProductInline(admin.TabularInline):
    model = CountryProduct

class CountryAdmin(admin.ModelAdmin):
    inlines = [CountryProductInline]

class ProductAdmin(admin.ModelAdmin):
    inlines = [CountryProductInline]

虽然这不是我预期的方式,但这给了我更好的解决方案......

答案 1 :(得分:0)

django管理员没有办法内置你需要的东西。

您可以创建自己的自定义视图,并以此方式执行。您可以向admin.ModelAdmin类添加额外的视图,这将完成您所需的操作。

答案 2 :(得分:0)

这可能是一个糟糕的设计。您的数据库表应包含正确的价格。

您的申请现在必须做两件事。它必须从其他地方(不在此表中)获得默认价格,并且还必须获得覆盖价格(来自此表)并将两条信息放在一起。

您无法轻松地使用您正在显示的网格类型来使用SQL。

你不能轻易让Django管理员使用你正在展示的网格。您可以尝试创建网格模板,但它对于这种多对多关系是唯一的,因此您还必须自定义Django管理视图以将模板用于一对多对多表,并使用普通默认模板对于所有其他表格。

要创建网格,您必须获取所有国家/地区和产品。然后,您必须创建适当的列表列表。然后,您可以编写自己的模板来显示它。在您拥有超过12个左右的国家之后,网格将会如此广泛以至于几乎无用。但对于前几个国家,你可以做到这一点。

您必须创建自己的模板和自己的视图功能才能执行此操作。

修改

“我愿意看看替代方法(包括模型结构的变化)以及满足要求”

哪个要求?糟糕的设计需要两个查询才能找到价格?这需要吗?

还是非常困难的网格布局?这需要吗?

目前尚不清楚“要求”是什么,因此不可能提出任何替代方案。只能说

  1. 分别查询base和overrides的SQL设计会更慢,更复杂。

  2. 具有单个值的SQL设计从“动态默认值”加载并且可以由用户更改(或不更改),这非常简单得多。这可以使用initial参数完成。 http://docs.djangoproject.com/en/dev/ref/forms/fields/#initial

  3. SQL无法轻松将多行转换为类似网格的结构。这需要复杂的SQL(远远超出ORM的能力)或视图函数中的Python处理。

  4. Django管理员根本不会做类似网格的结构。