【问题标题】:Querying Parent from the foreign key django从外键 django 查询父级
【发布时间】:2020-08-17 18:35:55
【问题描述】:

我有以下型号:

class CustomUser(AbstractBaseUser, PermissionsMixin):
    email = models.EmailField(unique=True)
    first_name = models.CharField(max_length=32)
    last_name = models.CharField(max_length=32)
    is_staff = models.BooleanField(default=False)
    is_active = models.BooleanField(default=True)
    date_joined = models.DateTimeField(default=timezone.now)

    USERNAME_FIELD = 'email' # unique identifier, changed to email (default was username)
    REQUIRED_FIELDS = ['first_name', 'last_name']

    objects = CustomUserManager() # custom manager for interacting with database

    def __str__(self):
        return self.email

class Refer(models.Model) :
    referred_by = models.ForeignKey(CustomUser, on_delete=models.CASCADE, default='admin', related_name='referred_by')
    referrals = models.ManyToManyField(CustomUser, related_name='referrals', blank=True)
    unique_ref_id = models.CharField(max_length=8, blank=True, default=generate())

    def __str__(self) :
        return f'Referred By: {self.referred_by}'

我想使用这个实现推荐系统,我有 unique_for_id 字段(例如“exbvagtl”),我如何在该用户下创建新推荐?

类似:Refer.objects.create(referred_by= CustomUser.objects.get(Refer__unique_ref_id='exbvagtl'))

我们非常欢迎更好的模型设计、资源和改进!

【问题讨论】:

  • 这是unique_for_id 唯一的per 用户,还是per 参考?
  • 对不起,它是 unique_ref_id 的错误,我认为这对两者都是唯一的? (因为他们有 OneToOne 关系)
  • 这里多个Refers可以引用相同 User作为refferred_by
  • 是的,我对如何设计模型架构感到困惑,这样每个用户都有 unique_ref_id 如果创建了任何其他用户,那么新用户将被放置在引用用户的推荐之下(即指向 unique_ref_id)
  • 一个用户可以有多个referred_bys吗?还是只有一个?

标签: django django-models django-queryset django-3.0 django-q


【解决方案1】:

我认为你把事情复杂化了。通过制作具有ForeignKeyCustomUserRefer 对象,这意味着每个CustomUser 可以有零个、一个或多个Refer 对象。虽然这不是不可能管理的,但它变得更难了,因为现在您的视图需要确保您使用正确的 Refer 对象,或者必须“连接”这些对象。此外,这意味着一个CustomUser 可以有多个unique_ref_ids。

问题是为什么我们首先需要这样的对象。您可以简单地在CustomUser 对象上构造一个unique_ref_id,然后将ForeignKey 添加到'self' 以指定推荐人是什么:

class CustomUser(PermissionsMixin, AbstractBaseUser):
    email = models.EmailField(unique=True)
    first_name = models.CharField(max_length=32)
    last_name = models.CharField(max_length=32)
    is_staff = models.BooleanField(default=False)
    is_active = models.BooleanField(default=True)
    date_joined = models.DateTimeField(auto_now_add=True)
    unique_ref_id = models.CharField(max_length=8, blank=True, default=generate)
    referred_by = models.ForeignKey(
        'self',
        related_name='referrals',
        null=True,
        default=None,
        on_delete=models.SET_NULL
    )

    USERNAME_FIELD = 'email' # unique identifier, changed to email (default was username)
    REQUIRED_FIELDS = ['first_name', 'last_name']

    objects = CustomUserManager() # custom manager for interacting with database

    def __str__(self):
        return self.email

因此,我们可以在此处添加另一个用户引用的用户:

CustomUser.objects.create(<b>referred_by_id=id_of_referred_user</b>)

如果稍后referred_by 用户被删除,那么它将被设置为NULL

您还可以通过以下方式查询用户推荐的用户:

myuser<b>.referrals.all()</b>

【讨论】:

  • 非常感谢!您能否指出一些解释将ForeignKey 指向自我的文档或资源。它的行为类似于 OneToMany 还是 ManyToOne?
  • @hac3r_0m:多对一,因此一个(可能是相同的)用户可以引用多个用户。见这里:docs.djangoproject.com/en/dev/ref/models/fields/…
  • 它给出了以下错误referred_by = models.ForeignKey(self, on_delete=models.SET_NULL, blank=True, null=True) NameError: name 'self' is not defined
  • @hack3r_0m:self 是一个字符串字面量,所以是'self',而不是self
【解决方案2】:

问题出在您的推荐系统设计上。通常,在推荐系统中,一个用户有一个推荐 ID。但是您的设计表明一个用户可以有多个refer_id。

我建议您将 unique_ref_id 移至 CustomUser 模型。这样你就可以做这样的事情:

Refer.objects.create(referred_by=CustomUser.objects.get(unique_ref_id="exbvagtl"))

第二条建议:把所有东西放在一张桌子上

你会注意到引用另一个人的人也是一个人,所以它基本上是对自我的引用。在这方面,您可以让您的 CustomUser 模型如下所示:

class CustomUser(AbstractBaseUser, PermissionsMixin):
    email = models.EmailField(unique=True)
    first_name = models.CharField(max_length=32)
    last_name = models.CharField(max_length=32)
    is_staff = models.BooleanField(default=False)
    is_active = models.BooleanField(default=True)
    date_joined = models.DateTimeField(default=timezone.now)
    referred_by = models.ForeignKey(self, on_delete=models.SET_NULL, blank=True, null=True)
    unique_ref_id = models.CharField(max_length=8, blank=True, default=generate())

    USERNAME_FIELD = 'email' # unique identifier, changed to email (default was username)
    REQUIRED_FIELDS = ['first_name', 'last_name']

    objects = CustomUserManager() # custom manager for interacting with database

    def __str__(self):
        return self.email

在此基础上,你可以这样做:

创建一个新用户:

sponsor = CustomUser.objects.get(unique_ref_id="exbvagtl")
user = CustomUser(email=email, first_name=first_name, last_name=last_name,referred_by=sponsor)
user.save()

获取用户推荐列表:

sponsor = CustomUser.objects.get(unique_ref_id="exbvagtl")
referrals = CustomUser.objects.filter(referred_by=sponsor)

希望对您有所帮助,如果您有任何疑问,请随时在下方提问。

【讨论】:

  • self 是字符串文字,所以是'self',而不是self
猜你喜欢
  • 1970-01-01
  • 2019-11-24
  • 2011-02-01
  • 2018-09-01
  • 2015-03-09
  • 1970-01-01
  • 1970-01-01
  • 2019-07-31
  • 2012-05-22
相关资源
最近更新 更多