3

我正在使用 Django 开发 Web 服务,我需要对一个非常具体、复杂的关系进行建模,而我无法解决。

想象三个通用模型,我们称它们为 Site、Category 和 Item。每个站点包含一个或多个类别,但它可以通过两种可能的方式之一与它们相关:一种是“常见”类别,它们处于多对多关系:它们是预定义的,每个站点可以与零相关或更多类别,反之亦然。其他类型的类别是为每个站点单独定义的,其中一个此类类别仅“属于”该站点,而不属于其他类别;即它们是多对一的关系,因为每个站点可能有许多这些类别。

在内部,这两种类型的类别完全相同,只是与站点相关的方式不同。但是,它可以将它们分成两个不同的模型(可能有一个共同的父模型),但这只能解决我的一半问题:Item 模型与 Categories 是多对一的关系,即每个 Item 属于只有一个类别,理想情况下它不应该关心它与站点的关系。

另一种解决方案是允许两种不同类型的站点-类别关系共存(即在同一个类别模型上同时具有 ForeignKey 和 ManyToMany 字段),但这种解决方案感觉就像打开了另一罐蠕虫。

有没有人知道这个死胡同是否有第三种更好的解决方案?

4

3 回答 3

4

为什么不在一个模型中同时包含两种类型的类别,所以您只有 3 个模型?

Site

Category
  Sites = models.ManyToManyField(Site)
  IsCommon =   models.BooleanField()

Item
  Category = models.ForeignKey(Category)

您说“在内部,这两种类别是完全相同的”。所以听起来这是可能的。请注意,ManyToManyField 只有一个值是完全有效的,因此您不需要“同一类别模型上的 ForeignKey 和 ManyToMany 字段”,这听起来很麻烦。只需在 ManyToMany 字段中输入一个值

于 2009-06-27T18:17:36.910 回答
1

作为替代实现,您可以使用 django 内容类型(通用关系)来完成项目的连接。使用此实现的一个好处是,它允许您根据未来的数据需求以不同的方式利用类别模型。

通过编写用于拉取和排序类别的模型方法,您可以更轻松地使用站点类别。Django 的 contrib admin 也支持通用关系内联。

您的模型如下:

Site(models.Model):
  label = models.CharField(max_length=255)

Category(models.Model):
  site = models.ManyToManyField(Site)
  label = models.CharField(max_length=255)

SiteCategory(models.Model):
  site = models.ForeignKey(Site)
  label = models.CharField(max_length=255)

Item(models.Model):
  label = models.CharField(max_length=255)
  content_type = models.ForeignKey(ContentType)
  object_id = models.PositiveIntegerField()
  content_object = generic.GenericForeignKey('content_type', 'object_id')

如需更深入地了解内容类型以及如何查询通用关系,您可以在此处阅读: http://docs.djangoproject.com/en/dev/ref/contrib/contenttypes/

于 2009-06-29T23:24:52.030 回答
0

警告:我知道对象-关系映射、Rails 和 Python,但不知道 Django。

我看到两个附加选项:

  1. 从数据库的角度考虑,我可以使多对多关系所需的表包含一个附加字段,该字段指示“普通”与“站点”关系,并添加约束以限制“站点”关系的类型。这可以在 Django 中完成,我认为,在“多对多关系的额外字段”部分。

如果您使用的是早期版本的 Django,您仍然可以通过使多对多表成为显式模型来做到这一点。

  1. 从对象的角度考虑,我可以看到将类别分为三个类:

    基本类别

    CommonCategory(基本类别)

    SiteCategory(BaseCategory)

然后使用 Django 的继承模型之一。

于 2009-06-27T20:08:51.877 回答