【问题标题】:Django query using related_name through another related_nameDjango 通过另一个related_name 使用related_name 查询
【发布时间】:2016-04-28 06:38:29
【问题描述】:

我有几个模型有一个 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='%(app_label)s_%(class)s_related'。为了便于解释,我将“userdetail_related”放在这里。
  2. 每个用户只有一个 UserDetail,但每个 UserDetail 有多个 UserInformation。
  3. 如果有未注册用户并且我们已经捕获了他们的电子邮件,则该电子邮件可以具有与其关联的 UserDetail 和 UserInformation,用于购物车客人结帐系统。

在我的视图中,我想从 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()

但这肯定会两次访问数据库,这是我不想要的。

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

【问题讨论】:

  • 对于任何给定的User,是否应该只有一个UserDetailUserInformation,还是可以有多个?
  • 作为侧节点,您的filter(user=self.request.user) 毫无意义,您已经确定每个用户详细信息都针对特定用户
  • @solarissmoke,见上面的编辑

标签: django django-models


【解决方案1】:

您可以使用以下内容:

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

此外,当您访问UserDetails 时,您实际上并不需要过滤器,因为您尝试从user 本身访问相关对象。所以跟随也可以。

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

顺便说一句,我认为你需要OneToOneField,因为一个user应该只有一个UserDetails

【讨论】:

    【解决方案2】:

    正如@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
    

    【讨论】:

      【解决方案3】:

      为了补充其他答案,关于布局的一些评论。

      对于模型名称,最好始终使用单数 (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,那么最好改用OneToOneFields。

      【讨论】:

        猜你喜欢
        • 2021-10-15
        • 1970-01-01
        • 2015-01-18
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多