>我有一个"集合"模型,它与"项目"模型有多对多关系。问题是"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
关系填充的额外字段(这与使用直通表时不能使用add
、clear
、remove
、delete
的原因相同)。您需要在使用 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的字段