使用OneToOneField扩展Django的用户模型:当不是每个用户都是CustomUser时,适当的post_save信号

时间:2018-03-30 18:54:17

标签: python django

我对extending the existing User model感兴趣,使用post_save方法将模型更新为

class LucyGuide(TimeStampedModel):
    user = models.OneToOneField(User, on_delete=models.CASCADE)
    bio = models.TextField(blank=True)

我关注https://simpleisbetterthancomplex.com/tutorial/2016/07/22/how-to-extend-django-user-model.html#onetoone,但我的用例存在差异:每个LucyGuide应该有一个关联的User,但不是每个User都是LucyGuide

如果我只是简单地转录'这个例子的代码,我相信我的接收器看起来像这样:

@receiver(post_save, sender=User)
def create_user_lucy_guide(sender, instance, created, **kwargs):
    if created:
        LucyGuide.objects.create(user=instance)


@receiver(post_save, sender=User)
def save_user_lucy_guide(sender, instance, **kwargs):
    instance.lucyguide.save()

但据我所知,第一种方法会使User成为LucyGuide,这不是我想要的。此外,第二种方法并不总是有效,因为不是每个User都有lucyguide。我会如下修改这个例子吗?

@receiver(post_save, sender=User)
def save_user_lucy_guide(sender, instance, **kwargs):
    if hasattr(instance, 'lucyguide'):
        instance.lucyguide.save()

更新

特别是,我试图了解如何应用docs中的以下引用:

  

这些配置文件模型在任何方面都不是特别的 - 它们只是恰好与用户模型具有一对一链接的Django模型。因此,在创建用户时不会自动创建它们,但可以使用django.db.models.signals.post_save来创建或更新相关模型。

我注意到这个简单的测试(使用factory_boy测试装置)已经没有任何post_save信号传递:

from django.test import TestCase
from lucy_web.test_factories import UserFactory, LucyGuideFactory


class LucyGuideTest(TestCase):
    def test_1(self):
        user = UserFactory()
        lucy_guide = LucyGuideFactory(user=user)

        user.first_name = "Andrea"
        user.save()

        self.assertEqual(lucy_guide.user.first_name, "Andrea")

那么博客文章中第二个post_save接收者的目的究竟是什么?是否有测试说明这是如何有用的?

1 个答案:

答案 0 :(得分:1)

如果您不需要为每个LucyGuide创建User,那么您就不需要create_user_lucy_guide信号。

博客文章说使用了第二个信号,因此您不必致电profile.save()。它给出的例子是:

def update_profile(request, user_id):
    user = User.objects.get(pk=user_id)
    user.profile.bio = 'Lorem ipsum dolor sit amet, consectetur adipisicing elit...'
    user.save()

我个人不喜欢这样。如果要更新save_user_lucy_guide,则更明确地删除第二个profile.save()信号并调用profile。然后,您不必担心在信号中添加if hasattr(user, lucyguide)检查,以防止在lucyguide不存在时出错。