我刚开始学习Python和Django,我正试图做一些非常简单的事情,但经过几个小时的搜索,我还没有找到答案,所以我的问题来了:
我必须模型:用户(自定义用户)和房子。
我想在User中有一个引用房子的字段,它可以是可选的,模拟一个人可以在房子里面(当引用被附加时)或房子外面(当引用为空时)的事实。在House模型中,我还希望有一个在给定时刻在房子里的人(用户)的"列表"。
为了实现这一点,我做了这样的事情:
class User(AbstractBaseUser):
# other attrs ...
# (ForeignKey) house: House where the user is right now
house = models.ForeignKey(House,
verbose_name='where is the user right now',
related_name='house_now', blank=True, null=True,
on_delete=models.SET_NULL
)
def leaveHouse(self):
house = self.house.delete()
class House(models.Model):
# (ManyToManyField) people: List of Users that are currently within the house
people = models.ManyToManyField(settings.AUTH_USER_MODEL,
verbose_name='people inside the house right now',
related_name='people',
blank=True
)
def removeUser(self, user):
self.people.remove(user)
问题是,当我使用User模型的函数leaveHouse时,它没有将ForeignKey设置为Null或Empty,而是删除了引用该键的House对象。
有什么关于我做错了什么、最佳实践之类的建议吗?
提前感谢!
编辑:
不管怎样,只是一个与此相关的小问题。为什么在django管理中,如果我将字段"house"设置为"----"(无"'NoneType'对象没有属性'pk'"
# (ForeignKey) home: Main house
home = models.ForeignKey(House,
verbose_name='default house',
related_name='home', blank=True, null=True,
on_delete=models.SET_NULL
)
不要删除相关的house
对象,而是将链接值设置为None
:
self.house = None
self.save()
我知道这个问题已经很老了,而且已经得到了回答,但我想指出的是,由于多种原因,您的模型设计不是最好的。
除非希望用户同时在多个房屋中,否则不应在房屋模型中设置ManyToMany字段。
当ManyToMany关系已经存在时,将外键用于House模型是错误的,因为您可以使用ManyToMany连接表设置用户和House之间的连接,并为外键设置null值。
关于使用ManyToMany字段的related_name
参数,我认为您理解错误。这是您将用于从用户模型访问房屋列表的名称user.<related_name>
。因此houses
是一个更好的选择。这同样适用于House模型的ForeignKey字段的related_name
,您可以使用它从House实例house.<related_name>
访问用户列表,在这种情况下people
将适用。
我链接了最新Django版本的文档,但这仍然适用于旧版本https://docs.djangoproject.com/it/4.0/ref/models/fields/#django.db.models.ForeignKey.related_name
鉴于此,当您使用removeUser
方法将用户从房子中移除时,您不会对ForeignKey进行操作,因为这是数据库中的另一个(冗余)关系。