Django通过另一个related_name使用related_name进行查询

时间:2016-04-28 06:38:30

标签: django django-models

我有几个模型将ForeignKey返回到一个模型,该模型将一个ForeignKey返回给Django中的auth User。

models.py

class UserDetails(models.Model):
    user = models.ForeignKey(
        settings.AUTH_USER_MODEL, 
        related_name='userdetail_related')
    details = models.CharField(max_length=100)
    email = models.EmailField(unique=True)

class UserInformation(models.Model):
    user = models.ForeignKey(
        UserDetails, 
        related_name='userinfo_related')
    info = models.CharField(max_length=100, default='this')

修改

  1. 根据Django文档,我对related_name的实际代码是:related_name ='%(app_label)s _%(class)s_related'。我把' userdetail_related'为了便于解释。
  2. 每个用户只有一个UserDetail,但每个UserDetail有很多UserInformation。
  3. 如果有未注册的用户并且我们已经抓取了他们的电子邮件,则该电子邮件可以将UserDetail和UserInformation与其关联,以用于购物车访客结账系统。
  4. 在我的视图中,我想从self.request.user访问UserInformation模型。

    我可以通过以下方式在我的视图中访问UserDetails:

    details = self.request.user.userdetail_related.filter(
        user=self.request.user).first()
    

    但我无法通过以下方式访问UserInformation:

    info = self.request.user.userdetail_related.filter(
        user=self.request.user).first().userinfo_related.filter(
        info='this').first()
    

    我能让它发挥作用的唯一方法是:

    details = self.request.user.userdetail_related.filter(
        user=self.request.user).first()
    
    info = details.userinfo_related.filter(
        info='this').first()
    

    但是这肯定会在数据库中击中两次,这是我不想要的。

    有没有人有更好的方法使用会话用户'通过'从UserInformation获取信息?的UserDetails?

3 个答案:

答案 0 :(得分:5)

您可以使用以下内容:

user_info = UserInformation.objects.filter(user__user=self.request.user).first()

此外,当您访问UserDetails时,您并不真正需要过滤器,因为您尝试从user本身访问相关对象。所以下面也可以。

details = self.request.user.userdetail_related.first()

作为附注,我认为您需要OneToOneField,因为一个user应该只有一个UserDetails

答案 1 :(得分:0)

正如@AKS建议的那样,您应该使用OneToOneField将模型与User相关联。你可以这样做:

class UserDetails(models.Model):
    user = models.OneToOneField(
        settings.AUTH_USER_MODEL, 
    related_name='userdetail_related')
    details = models.CharField(max_length=100)

class UserInformation(models.Model):
    user = models.OneToOneField(
        UserDetails, 
        related_name='userinfo_related')
    info = models.CharField(max_length=100, default='this')

然后您可以像这样访问UserInformationUserDetails

details = self.request.user.userdetail_related.details
info = self.request.user.userinfo_related.info

答案 2 :(得分:0)

要添加其他答案,请注意有关布局的一些评论。

对于模型名称,最好始终使用单数(UserDetails - > UserDetail),而不是复数。然后,对于ForeignKey的相关名称,使用复数(因为反向查找可能会找到多个具有向后关系的项目。)

class UserDetail(models.Model):
    user = models.ForeignKey(settings.AUTH_USER_MODEL, related_name='details')
    details = models.CharField(max_length=100)

class UserInformation(models.Model):
    user = models.ForeignKey(settings.AUTH_USER_MODEL, related_name='info')
    info = models.CharField(max_length=100, default='this')

使视图中的访问更加简单

request.user.infos.all().first()
request.user.details.filter(info__startswith="something")

另外,如果可行的话,将两者都添加到User对象上,因为"flat is better than nested"

如果每个User只有一个UserDetail和一个UserInformation,则最好使用OneToOneField