【问题标题】:Better way to represent Many to many relationship in django admin在 django admin 中表示多对多关系的更好方法
【发布时间】:2010-02-25 07:00:35
【问题描述】:

我有一个独特的问题,应该在 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

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

只要满足要求,我愿意考虑替代方法(包括模型结构的更改)...您的任何形式的输入肯定对我有用...

在此先感谢 :)

【问题讨论】:

    标签: python django django-models django-admin


    【解决方案1】:

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

    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]
    

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

    【讨论】:

      【解决方案2】:

      django 管理员没有内置的方法来执行您需要的操作。

      您可以创建自己的自定义视图,并以这种方式进行。您可以向 admin.ModelAdmin 类添加额外的视图,这将满足您的需要。

      【讨论】:

        【解决方案3】:

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

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

        您不能轻易地使 SQL 与您所显示的那种网格一起工作。

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

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

        您必须创建自己的模板和自己的视图函数才能做到这一点。

        编辑

        “只要满足要求,我愿意考虑替代方法(包括模型结构的更改)”

        什么要求?需要两次查询才能找到价格的糟糕设计?是必须的吗?

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

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

        1. 单独查询基和覆盖的 SQL 设计会更慢且更复杂。

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

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

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

        【讨论】:

        • 这不是一个完整的设计,只是想简化问题,这就是以这种方式表示的原因......你是对的,以这种方式呈现网格不是一个好主意,但这只是我的选择之一......
        • 能否详细说明第 2 项:动态默认值?这个“覆盖”的问题是我自己遇到过的,并且从来没有觉得实施起来很舒服。是否有任何文章探讨了这个问题('sql overrides' 太笼统了,无法让megooglethatforyou)。
        • “动态默认值”只是一个默认值,它不是在模型中静态定义的,而是根据当前数据、事务状态或其他东西动态加载的。它只是一个在运行时动态加载到表单中的默认值。阅读:docs.djangoproject.com/en/dev/ref/forms/fields/#initial
        猜你喜欢
        • 1970-01-01
        • 2012-10-20
        • 2011-08-07
        • 1970-01-01
        • 1970-01-01
        • 2017-12-07
        • 2016-12-14
        • 2011-02-25
        • 2013-06-17
        相关资源
        最近更新 更多