【问题标题】:Django: Same model with different features?Django:相同的模型具有不同的功能?
【发布时间】:2020-01-30 22:20:30
【问题描述】:

对象模型:

class Object(models.Model):
    author = models.ForeignKey(ProfileUser, on_delete=models.CASCADE)
    title = models.CharField(max_length=300)
    category = models.ForeignKey(Category, on_delete=models.CASCADE)
    address = models.CharField(max_length=300)
    content = models.TextField()
    created_date = models.DateTimeField(default=timezone.now)
    approved_object = models.BooleanField(default=False)
    admin_seen = models.BooleanField(default=False)

    def __str__(self):
        return f"{self.title}"

类别型号:

class Category(models.Model):
    title = models.CharField(max_length=50)

    def __str__(self):
        return f"{self.title}"

例如,我有一些类别,如酒店、餐馆等。所以我希望每个类别都有不同的功能(添加新的单选按钮),但我不确定如何正确处理它。酒店必须有房间,游泳池等。餐馆必须有乡村厨房,座位等。将来我会有其他类别。

问题是:这是最好的方法(实践)。

我的解决方案:创建第三个表,其中包含特征和每个类别以具有列 features 并用逗号分隔存储特征,但基于 DB normalization 并不是很好的解决方案。

【问题讨论】:

  • 我建议阅读这篇文章!它可能会给您的用例带来很好的启发! https://realpython.com/modeling-polymorphism-django-python/

标签: python mysql django normalization


【解决方案1】:

您可以使用multi-table inheritance

你定义一个基础对象,然后你可以定义不同的子对象来共享父对象的属性

在你的情况下,看起来像这样:

class Object(models.Model):
    ...


class Restaurant(Object):
   seats = IntegerField(...)
   reservations = ManyToManyField(...)

class Hotel(Object):
   rooms = IntegerField(...)
   has_pool = BooleanField(...)

Django 将自动为您创建关系并管理查询。要获取所有餐厅,您可以使用Restaurant.objects.all(),但有一个限制。查询Object.objects.all() 时,您将获得Objects 的列表,而不是它们的特定子类。如果我没记错的话,您可以通过(例如)object.restaurant 访问特定实例。

如果您确实想获取特定对象,可以查看名为 Django-polymorphic 的库。

【讨论】:

  • 嗯,看起来很不错,但现在,我无法检查这个解决方案,所以仍然不能接受这个答案,但你现在有我的支持 :)
  • 好的,它工作正常。还有一个问题,现在它可以与下拉列表一起使用(选择类别,将 AJAX 发送到 views.py 并取决于参数(类别)通过 switch case 为每个类别显示不同的形式(python 中的 if else 语句))是否有更聪明的方式来显示不同的形式?
  • 是否可以为不同的模型添加一个 form_class 字段?然后你可以简单地从对象中调用表单,比如form_class = RestaurantForm
  • 是的,但是以后每个餐厅都会有,还会有重复。另外,如果我想自动化它(如果我像现在一样为每个类别创建链接,并为每个类别调用对象,现在我应该使用 if 语句)?主要问题是我现在无法区分不同的类别(因为它们没有唯一的,例如 category_id 或其他)
【解决方案2】:

你可以使用abstract base classes:

当您想将一些通用信息放入许多其他模型中时,抽象基类很有用。您编写基类并将 abstract=True 放在 Meta 类中。该模型将不会用于创建任何数据库表。相反,当它用作其他模型的基类时,它的字段将添加到子类的字段中。

然后你可以让你的RestaurantHotel 模型继承这个抽象类。然后,Django 将创建两个表,其中包含来自抽象类的基本字段以及来自每个模型的特定字段。

【讨论】:

  • 使用抽象基类并不能查询所有“对象”,对吧?
  • 它没有,你是对的,但这是@MorganFreeFarm 的要求吗?
  • 我不知道,只是检查;)
【解决方案3】:

我会一一解释:

  • category 表包含所有类别。
  • 现在每个类别可能都有一些共同和独特的功能。features 将与category 表有many to many 关系。
    所以我们创建feature_master 表并将其与类别表进行映射。
  • feature_master 表包含所有功能。
  • category_feature_map表是映射表(联结表)
  • object 表包含有关对象的所有详细信息,object_detail 表将包含特定对象的所有 feature

【讨论】:

  • 谢谢你的回答,但从Django开发的角度来看,我认为上面的解决方案更好:)
  • db 应该独立于 o.r.m。总是。所以如果我们想及时改变框架,我们就不用担心数据库了。 db 应该始终独立于 orm
猜你喜欢
  • 2017-03-29
  • 1970-01-01
  • 2018-03-03
  • 1970-01-01
  • 2018-06-16
  • 2017-12-25
  • 1970-01-01
  • 1970-01-01
  • 2012-08-27
相关资源
最近更新 更多