【问题标题】:A better way of representing two extremely similar, yet different objects in Django?在 Django 中表示两个极其相似但不同的对象的更好方法?
【发布时间】:2016-07-26 03:56:42
【问题描述】:

所以我正在尝试创建一种对“房屋”和“房屋组”进行建模的好方法。

房屋和房屋组非常相似,它们都带有描述和相关的定价信息。

但是,“bookings”只能分配给 Houses 而不能分配给 HouseGroups。

目前,我的模型如下所示:

class Houselike(models.Model):
    max_guests = models.IntegerField()
    name = models.CharField(max_length=20)
    description = models.TextField(blank=True)

class House(Houselike):
    pass

class HouseGroup(Houselike):
    houses = models.ManyToManyField(House)

从语义上讲,这实际上非常接近我想要的。但是,在数据库中,这会导致存在两个表,它们都只有一个字段“houselike_ptr_id”,指的是“Houselike”基础对象。

因此,检查 Houselike 对象是 House 还是 Housegroup 需要查看两个不同的表。

更有效的选择是:

class Houselike(models.Model):
    max_guests = models.IntegerField()
    name = models.CharField(max_length=20)
    description = models.TextField(blank=True)
    is_group = models.BooleanField()
    houses = models.ManyToManyField(House)

这导致“houselike”表中只有一个额外的字段,而包含相关房屋的另一个表只有在我们实际查找它们时才会被命中。从存储的角度来看,这是最好的解决方案,恕我直言。

但是,从语义的角度来看,这并不是那么好:房屋和房屋组相似,但对象不同。

此外,这允许诸如包含其他家庭组的家庭组、包含家庭的非组之类的东西,我必须手动检查的东西。

我也非常喜欢能够明确地使用 HouseHouseGroup 对象。用同一个班级代表他们俩感觉不对。

有没有更好的方法来做到这一点?

编辑:

我忘了提到定价信息(以及其他实体)可以与 House 或 Housegroup 相关联,并且(大致)实现如下:

class PricePeriod(models.Model):
    house = models.ForeignKey(Houselike, on_delete=models.CASCADE)
    arrival_date = models.DateField()
    # Date of last departure date
    departure_date = models.DateField()
    price = models.DecimalField(max_digits = 10, decimal_places=2)

这就是为什么我不简单地把 Houselike 做成一个抽象模型,因为这些其他对象都与它相关。

【问题讨论】:

    标签: django database data-modeling


    【解决方案1】:

    事实证明,这就是所谓的“单表继承”,在我的情况下是完美的。

    而且,这是互联网,有一个应用程序:https://github.com/craigds/django-typed-models

    from typedmodels.models import TypedModel
    
    # Create your models here.
    
    class Houselike(TypedModel):
        max_guests = models.IntegerField()
    name = models.CharField(max_length=20)
    description = models.TextField(blank=True)
    
    class House(Houselike):
        pass
    
    class HouseGroup(Houselike):
        houses = models.ManyToManyField(House)
    

    这几乎完全符合我的要求:数据库中的单个表,以及 Python/Django 中的明确、语义正确的模型。

    现在我只需要修复我糟糕的命名...

    【讨论】:

      猜你喜欢
      • 2020-05-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-06-15
      • 1970-01-01
      相关资源
      最近更新 更多