如何避免django的“与相关m2m字段冲突”错误?

3 投票
2 回答
4593 浏览
提问于 2025-04-16 15:11

我有很多模型需要投票功能,所以我创建了这样的结构:

class Voteable(models.Model):
    likes_balance = models.IntegerField(default=0, editable=False)
    votes = models.ManyToManyField(User, blank=True, editable=False)
    likes = models.ManyToManyField(User, blank=True, editable=False)

    class Meta:
        abstract = True

class Item(Voteable):
    title = models.CharField(max_length=20, db_index=True)
    description = models.TextField(max_length=1000)
    contact_user = models.ForeignKey(User, null=True, blank=True)

    class Meta:
        abstract = True

class Movie(Item):
    cover = models.ImageField(upload_to='images/covers/')

class Car(Item):
    seller = models.CharField(max_length=50)

当我尝试用“python manage.py syncdb”来创建表时,出现了错误信息:

“m2m字段'likes'的访问器与相关字段'User.movie_set'冲突。请在'likes'的定义中添加一个related_name参数。”

当然,我在Item类中还有很多其他字段,所以我不想把它们都复制到所有子类中,只是想像错误提示那样设置related_name。

有没有什么建议可以解决这个问题?

2 个回答

2

通常,如果你在你的多对多关系定义中添加一个related_name,应该就能正常工作:

class Voteable(models.Model):
    likes_balance = models.IntegerField(default=0, editable=False)
    votes = models.ManyToManyField(User, blank=True, editable=False, related_name='votes')
    likes = models.ManyToManyField(User, blank=True, editable=False, related_name='likes')

    class Meta:
        abstract = True

这是因为如果不这样做,Django会在Voteable表中添加两个user_id,这样就会出现冲突,因为有两个相同的列名。添加一个related_name可以强制Django使用你指定的related_name,而不是使用{外部表名}_id这个列名。

希望这能帮到你。

10

我在Django的文档中找到了一个解决方案。

在抽象模型中,可以写一些这样的内容:related_name="%(app_label)s_%(class)s_related"

撰写回答