Django三种模型关系适用场景及示例代码正确性咨询
模型关系合理性评估与问题解答
现有代码的问题
你当前的Watchlist模型关系设计存在逻辑冲突,问题出在ForeignKey(User)和ManyToManyField(Listing)的组合上,不符合你预期的「每个用户一个关注清单,清单里存多个商品」的业务逻辑。
问题1:Watchlist.item字段应该用ForeignKey吗?当前使用M2M是否正确?
你当前用M2M的逻辑不对,但也不是直接换成ForeignKey就完事,得看你对Watchlist的定位:
- 如果你把
Watchlist定义为单条关注记录(一条记录=一个用户关注了一个商品):那item必须用ForeignKey(Listing),user用ForeignKey(User),这种设计最灵活,后续加关注时间、关注时的商品价格这类附加字段也很方便。 - 如果你把
Watchlist定义为用户的整个关注清单(一个用户只有一条Watchlist记录):那item用M2M是可以的,但对应的user字段必须改成OneToOneField,否则会出现同一个用户生成多条关注清单的bug。
问题2:是否可以将Watchlist功能集成到User类中,给用户新增一个存储Listing ID的空列表来简化实现?
不要用存ID列表的方案,这是关系型数据库设计的典型反模式:不仅会丢失外键约束,所有跨表查询都无法走索引,后续要查「某件商品被哪些用户关注」这类需求的时候性能会非常差。
如果想简化代码,完全可以不用单独建Watchlist表,直接在User模型上加M2M字段关联Listing即可:
class User(AbstractUser): watched_listings = models.ManyToManyField(Listing, related_name="watchers")
Django会自动生成中间表存储关联关系,增删查改都有ORM原生支持,比你自己维护ID列表简单得多。
问题3:若每个Watchlist仅属于单个用户,且每个用户仅拥有一个关注清单,为什么Watchlist.user不使用One-to-one关系?
如果你的业务规则确实是「一个用户只能有一个关注清单」,那Watchlist.user本来就应该用OneToOneField,而不是ForeignKey。ForeignKey是多对一关系,默认允许多个Watchlist关联同一个User,和你的业务规则冲突;只有OneToOneField会强制约束「一个用户只能对应一条Watchlist记录」,刚好匹配你的需求。
内容的提问来源于stack exchange,提问作者Spinfire
相关产品推荐
相关产品推荐

