是否(以及如何)通过django中的公共中介/连接表处理多个多对多关系?

时间:2022-10-04 19:18:11

I have several models that implement a so called 'Taggable' behavior:

我有几个模型实现了所谓的'Taggable'行为:

class Tag(models.Model):
    name = models.CharField(max_length=200)


class Taggable(models.Model):
    tags = models.ManyToManyField(Tag)

    class Meta:
        abstract = True


class A(Taggable):
...

class B(Taggable):
...

class C(Taggable): 
...

class D(Taggable):
...

This scenario causes an intermediary table to be created for each and every model inheriting from Taggable. I.e.,

此方案导致为从Taggable继承的每个模型创建中间表。即,

appname_a_tags
appname_b_tags
appname_c_tags
appname_d_tags

I am still at the beginning of the development, and the number of such models and thus tables might increase. So, it bothers me a little to have a clutter of tables with similar data, plus, in the future, I might need common functionality for all the tags assigned in the application (e.g., collecting statistical data of which tags used where, or maybe for a search feature).

我仍处于开发阶段,这些模型和表格的数量可能会增加。因此,让我感到困扰的是,有一些具有类似数据的表格混乱,而且,在将来,我可能需要为应用程序中分配的所有标签提供通用功能(例如,收集在哪里使用哪些标签的统计数据,或者可能用于搜索功能)。

Now, my question is: from general engineering perspective would it be feasible to use one common intermediary/join table for all of the models consuming this 'Taggable' behavior? If so, what would be the disadvantages of doing so, and would be the best approach to tackle this.

现在,我的问题是:从一般工程角度来看,为所有使用这种“Taggable”行为的模型使用一个公共中介/连接表是否可行?如果是这样,这样做的缺点是什么,并且是解决这个问题的最佳方法。

Being new in django, I would have tried (or researched more on) these 2 scenarios if I had to do it:

作为django的新手,如果我不得不这样做,我会尝试(或研究更多)这两个场景:

SCENARIO 1:

情景1:

  • include a 'class' field in the Tag model above that will keep the type of ojbect that the tag is assigned to (e.g., A, B, C, or D)
  • 在上面的Tag模型中包含一个'class'字段,它将保留标记所分配的ojbect的类型(例如,A,B,C或D)
  • create a proxy Tag class for each of A, B, C, D (e.g., ATag, BTag, ..), override the models.Model class' 'save' method in order to update 'class' column appropriately. I would also have to customize model's manager in order to filter and properly retrieve tags that belong to that class only.
  • 为A,B,C,D(例如,ATag,BTag,..)中的每一个创建代理Tag类,覆盖models.Model类''save'方法,以便适当地更新'class'列。我还必须自定义模型的管理器,以便过滤并正确检索仅属于该类的标签。
  • let each class consume its custom Tag class. I.e.,

    让每个类使用其自定义Tag类。即,

    class A(models.Model):
        tags = models.ManyToManyField(ATags)
        ...
    

SCENARIO 2:

情景2:

  • create a common intermediary model TagAssigned, and include the extra 'class' field besides the 2 foreign keys for the tag and the item tagged
  • 创建一个公共中介模型TagAssigned,并包括除标签和标记的项目的2个外键之外的额外“类”字段
  • use TagAssigned as intermediary table for all 4 classes. E.g.,

    使用TagAssigned作为所有4个类的中间表。例如。,

    Class A(models.Model)
        tags = models.ManyToManyField(Tag, through='TagAssigned')
        ...
    
  • override and customize the 'save' methods and the model managers of classes A, B, C, and D (as opposed to proxy models in scenario 1)

    覆盖和自定义“保存”方法以及类A,B,C和D的模型管理器(与方案1中的代理模型相对)

1 个解决方案

#1


1  

I would suggest to keep your initial implementation as simple as possible (e.g. no proxy table no overwriting save) and not to worry about number of tables unless you reach some pretty amazing numbers, hit some kind of serious issues with it or or outgrow the usefulness of "simple tags". This might save you one hairy implementation that you might have not needed in the first place.

我建议尽可能简单地保持你的初始实现(例如没有代理表没有覆盖保存)并且不要担心表的数量,除非你达到一些非常惊人的数字,遇到某种严重问题或者或者超出实用性“简单标签”。这可能会为您节省一个您可能首先不需要的多毛实现。

P.S. I am using https://github.com/alex/django-taggit which is pretty handy and easy to work with. Just saw that the repo has ~60 issues in gitgub :) but I have not hit any of them.

附:我正在使用https://github.com/alex/django-taggit,这非常方便,易于使用。刚刚看到repo在gitgub中有大约60个问题:)但我还没有碰到任何一个。

#1


1  

I would suggest to keep your initial implementation as simple as possible (e.g. no proxy table no overwriting save) and not to worry about number of tables unless you reach some pretty amazing numbers, hit some kind of serious issues with it or or outgrow the usefulness of "simple tags". This might save you one hairy implementation that you might have not needed in the first place.

我建议尽可能简单地保持你的初始实现(例如没有代理表没有覆盖保存)并且不要担心表的数量,除非你达到一些非常惊人的数字,遇到某种严重问题或者或者超出实用性“简单标签”。这可能会为您节省一个您可能首先不需要的多毛实现。

P.S. I am using https://github.com/alex/django-taggit which is pretty handy and easy to work with. Just saw that the repo has ~60 issues in gitgub :) but I have not hit any of them.

附:我正在使用https://github.com/alex/django-taggit,这非常方便,易于使用。刚刚看到repo在gitgub中有大约60个问题:)但我还没有碰到任何一个。