首页 > 解决方案 > 如何修复“Follow.s_id”不是“用户”的外键。”在这个模型中

问题描述

我是 Django 框架的新手,我正在尝试构建以下系统,其中包含关注多个股票的用户并且股票被多个人关注,我正在尝试使用中间类创建复合键,但我有这个错误。



class Stock(models.Model):
    symbol = models.CharField(max_length=12, primary_key=True,default="")
    name = models.CharField(max_length=64)
    top_rank = models.IntegerField(null=True)
    price = models.FloatField()
    change = models.FloatField(null=True)
    change_percent = models.FloatField()
    market_cap = models.FloatField(null=True)
    primary_exchange = models.CharField(null=True, max_length=32) # NASDAQ
    followers = models.ManyToManyField('myapp.Users',through='Follow',through_fields=('u_id','s_id'))


class Users(models.Model):
    user_id = models.IntegerField(primary_key=True,default="")
    name = models.CharField(max_length=12)

class Follow(models.Model):
    u_id=models.ForeignKey('Users',on_delete=models.CASCADE)
    s_id=models.ForeignKey('Stock',on_delete=models.CASCADE)



myapp.Stock.followers: (fields.E339) 'Follow.s_id' is not a foreign key to 'Users'.
        HINT: Did you mean one of the following foreign keys to 'Users': u_id?
myapp.Stock.followers: (fields.E339) 'Follow.u_id' is not a foreign key to 'Stock'.
        HINT: Did you mean one of the following foreign keys to 'Stock': s_id?

标签: django-models

解决方案


through_fields[Django-doc]的顺序不正确。如文档中所述:

through_fields接受一个 2-tuple ('field1', 'field2'),其中是定义在(...)上field1模型的外键名称,以及ManyToManyField目标模型(...)field2的外键名称。

所以这意味着 的第一项through_fields应该在's_id'这里,因为它指的是Stock模型,您定义 的模型,ManyToManyField第二项应该是'u_id'

class Stock(models.Model):
    # …
    followers = models.ManyToManyField(
        'myapp.Users',
        through='Follow',
        through_fields=('s_id','u_id')
    )

话虽如此,您无需在through_fields此处定义,因为您的Follow模型恰好包含两个ForeignKey指向不同模型的 s。事实上,您也不需要定义through=...模型,因为它不包含任何额外的字段。

请注意,通常 aForeignKey不包含后缀,因为 Django_id自动添加一个额外的字段,其_id后缀包含引用值的主键。

因此,将模型定义为:

class Stock(models.Model):
    symbol = models.CharField(max_length=12, primary_key=True)
    name = models.CharField(max_length=64)
    top_rank = models.IntegerField(null=True)
    price = models.FloatField()
    change = models.FloatField(null=True)
    change_percent = models.FloatField()
    market_cap = models.FloatField(null=True)
    primary_exchange = models.CharField(null=True, max_length=32) # NASDAQ
    followers = models.ManyToManyField('myapp.User')


class User(models.Model):
    user_id = models.IntegerField(primary_key=True)
    name = models.CharField(max_length=12)

请注意,模型通常有一个单数名称,所以User,而不是Users


推荐阅读