无法在 Django 中共享基类的两个模型上定义"通过"关系



>我有一个"集合"模型,它与"项目"模型有多对多关系。问题是"set"是 Item 的子类(所有内容都是项目中的 Item)。

它工作正常,直到我尝试与称为"订单"的中间模型创建"通过"关系,我正在定义该模型,以便我可以对"集合"中的"项目"进行排序。

当我尝试定义关系时,出现此错误:

ERRORS:
curate.Set.items_: (fields.E001) Field names must not end with an underscore.
curate.order.set: (fields.E304) Reverse accessor for 'order.set' clashes with reverse accessor for 'order.item'.
HINT: Add or change a related_name argument to the definition for 'order.set' or 'order.item'.

我尝试将related_name添加到Order.set和Order.item,但它似乎不起作用。我可以让迁移感到满意,但是当我尝试迁移时,我收到一条错误消息:

ValueError: Cannot alter field curate.Set.items into curate.Set.items - they are not compatible types (you cannot alter to or from M2M fields, or add or remove through= on M2M fields)

models.py


class Item(models.Model, AdminVideoMixin):
title = models.TextField(max_length=5000)
slug = models.SlugField(max_length=5000, default='')
...
class Video(Item):
video_embed = EmbedVideoField(max_length=500)
...
class Article(Item):
authors = models.CharField(max_length=10000)
...
class Podcast(Item):
categories = models.CharField(max_length=5000, null=True, blank=True,)
...
class Episode(Item):
author = models.CharField(max_length=10000, null=True,blank=True,)
...
class Set(Item):
items = models.ManyToManyField(Item, related_name='setItems', max_length=5000, through='Order')
front_page = models.BooleanField(max_length=300, blank=False, default=False, null=False)
class order(models.Model):
item = models.ForeignKey(Item, on_delete=models.CASCADE,)
set = models.ForeignKey(Set, on_delete=models.CASCADE,)
order = models.CharField(max_length=64, default=0)

创建ManyToMany字段后,无法将其更改为使用through关系。这是因为直通表现在将包含无法由标准ManyToMany关系填充的额外字段(这与使用直通表时不能使用addclearremovedelete的原因相同)。您需要在使用 through 关系的Set上创建一个新的ManyToMany字段,然后在删除Set.items之前用Set.items中的数据填充该字段。

通过表的文档

如果需要将新字段称为items,则可以执行以下操作:

  • Set模型中将items更改为items_old,如果您希望相同,还需要更改related_name(进行并运行迁移)
  • 添加具有直通关系的新items字段(进行并运行迁移)
  • 使用来自items_old的数据填充新的items字段
set_items = Set.objects.filter(items__isnull=False)
Order.objects.bulk_create([
Order(item=item, set=s)
for s in set_items
for item in s.items.all()
])
  • Set中删除items_old

注意 - 就像katoozi在他的评论中提到的那样,你可能不应该有名为set的字段

最新更新