我应该为标签使用 ArrayField 还是 ManyToManyField

Should I use ArrayField or ManyToManyField for tags

我正在尝试为 django 中的 postgres 数据库添加标签,我找到了两个解决方案:

使用外键:

class Post(models.Model):
    tags = models.ManyToManyField('tags')
    ...

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

使用数组字段:

from django.contrib.postgres.fields import ArrayField

class Post(models.Model):
    tags = ArrayField(models.CharField(max_length=140))
    ...

假设我不关心在我的代码中支持其他数据库后端,推荐的解决方案是什么?

如果您希望监视 class 标签(例如:有多少标签,有多少特定标签等),请选择第一个选项,因为您可以向模型添加更多字段并将丰富应用程序。

另一方面,如果您只是为了显示或最少的处理而希望它成为数组列表,请选择该选项。

但如果您希望节省时间并丰富应用程序,您可以使用此

https://github.com/alex/django-taggit

初始化就这么简单:

from django.db import models

from taggit.managers import TaggableManager

class Food(models.Model):
# ... fields here

    tags = TaggableManager()

并且可以通过以下方式使用:

>>> apple = Food.objects.create(name="apple")
>>> apple.tags.add("red", "green", "delicious") 
>>> apple.tags.all()
[<Tag: red>, <Tag: green>, <Tag: delicious>]

如果使用数组字段,

  • 数据库中每一行的大小会有点大,因此 Postgres 会使用更多 toast tables

  • 每次获取行时,除非您专门使用 defer 字段或以其他方式通过仅或值或其他方式将其从查询中排除,否则您需要支付加载所有内容的费用每次遍历该行时这些值。如果这就是您所需要的,那就这样吧。

  • 基于该数组中的值进行过滤,虽然可能不会那么好,而且 Django ORM 并不像它对 M2M 表那样明显。

如果使用M2M字段,

  • 您可以更轻松地过滤这些相关值 这些字段在默认情况下被推迟,如果需要,您可以使用 prefetch_related,如果您只想加载这些值的一个子集,则可以使用它们。

  • 由于密钥和额外的 ID 字段,M2M 的数据库总存储量会略高。

  • 由于键的存在,这种情况下的连接成本完全可以忽略不计。

话虽如此,以上答案不属于我。前段时间,我在学习 Django 时无意中遇到了这个困境。我在这里找到了这个问题的答案,Django Postgres ArrayField vs One-to-Many relationship

希望你得到你想要的东西。