【问题标题】:Inheritance in Django: child class updates parent with empty fieldsDjango 中的继承:子类使用空字段更新父类
【发布时间】:2015-06-02 19:00:11
【问题描述】:

我正在为使用 django.contrib.auth 创建的每个用户创建一个 UserProfile,方法是扩展基本抽象用户并在新用户注册时捕获信号(我更喜欢为配置文件提供单独的表):

class UserProfile(auth_models.User):
    objects = UserProfileManager()
    organization = models.CharField(max_length=100)
    country = CountryField()
    is_verified = models.BooleanField(default=False)
    blocked = models.BooleanField(default=False)
    anonymous = models.BooleanField(default=False)

@django_dispatch.receiver(
    django_signals.post_save, sender=auth_models.User
)
def user_migrated(sender, instance, created, raw, **kwargs):
    if not created or raw:
        return
    if instance.pk != 1:
        return
    account_models.UserProfile.objects.create(
        user_ptr=instance,
        organization='The SATNet Network',
        country='US'
    )

问题是,每次我创建用户时,首先正确插入基本用户,但配置文件的创建会引发 Django “更新”刚刚创建的基本用户为空值:

DEBUG (0.001) INSERT INTO "auth_user" ("password", "last_login", "is_superuser", "username", "first_name", "last_name", "email", "is_staff", "is_active", "date_joined") VALUES ('pbkdf2_sha256$15000$TacxtITENWvn$e6LbDUtE1XcAwz/Kfj6vNj40yQurEOcBCRJe6LrBTls=', '2015-06-02 18:48:32.826604+00:00', true, 'satnet_admin', '', '', 'satnet.calpoly@gmail.com', true, true, '2015-06-02 18:48:32.826604+00:00') RETURNING "auth_user"."id"; args=('pbkdf2_sha256$15000$TacxtITENWvn$e6LbDUtE1XcAwz/Kfj6vNj40yQurEOcBCRJe6LrBTls=', '2015-06-02 18:48:32.826604+00:00', True, 'satnet_admin', '', '', 'satnet.calpoly@gmail.com', True, True, '2015-06-02 18:48:32.826604+00:00')
DEBUG (0.001) UPDATE "auth_user" SET "password" = '', "last_login" = '2015-06-02 18:48:32.886904+00:00', "is_superuser" = false, "username" = '', "first_name" = '', "last_name" = '', "email" = '', "is_staff" = false, "is_active" = true, "date_joined" = '2015-06-02 18:48:32.886951+00:00' WHERE "auth_user"."id" = 1; args=('', '2015-06-02 18:48:32.886904+00:00', False, '', '', '', '', False, True, '2015-06-02 18:48:32.886951+00:00', 1)
DEBUG (0.000) INSERT INTO "accounts_userprofile" ("user_ptr_id", "organization", "country", "is_verified", "blocked", "anonymous") VALUES (1, 'The SATNet Network', 'US', false, false, false); args=(1, 'The SATNet Network', 'US', False, False, False)
Superuser created successfully.

如果我不创建配置文件,则用户已正确插入,因为 Django 不更新模型:

DEBUG (0.001) INSERT INTO "auth_user" ("password", "last_login", "is_superuser", "username", "first_name", "last_name", "email", "is_staff", "is_active", "date_joined") VALUES ('pbkdf2_sha256$15000$nxWaMTdYVVKO$MGWYHw/NXoEwCxBryK+bYOoqTYsO0DXgyqkBEQNxq/I=', '2015-06-02 18:53:54.716366+00:00', true, 'satnet_admin', '', '', 'satnet.calpoly@gmail.com', true, true, '2015-06-02 18:53:54.716366+00:00') RETURNING "auth_user"."id"; args=('pbkdf2_sha256$15000$nxWaMTdYVVKO$MGWYHw/NXoEwCxBryK+bYOoqTYsO0DXgyqkBEQNxq/I=', '2015-06-02 18:53:54.716366+00:00', True, 'satnet_admin', '', '', 'satnet.calpoly@gmail.com', True, True, '2015-06-02 18:53:54.716366+00:00')
Superuser created successfully.

处理这个问题的正确方法是什么? Django 总是这样更新模型还是我遗漏了什么?

环境:Python 3.4.2 + Django 1.7.4 + PostgreSQL)

【问题讨论】:

  • 我看到您正在使用自定义管理器UserProfileManager。你实现了自己的create 方法吗?
  • @rojoca:不,我没有在我的自定义管理器中实现 create 方法,但我没想到 Django 会表现出这种行为……这是继承方面的正常行为吗?

标签: python django python-3.x inheritance django-models


【解决方案1】:

我怀疑问题在于您是从auth_models.User 继承的。这是多表继承,并不适合这种情况。在此处查看 django 文档:https://docs.djangoproject.com/en/1.8/topics/auth/customizing/#extending-django-s-default-user

这基本上是说如果您想将配置文件数据存储在单独的表中,则无需扩展auth_models.User。只需使用OneToOneFieldauth_models.User 创建一个模型:

class UserProfile(models.Model):
    objects = UserProfileManager()
    organization = models.CharField(max_length=100)
    country = CountryField()
    is_verified = models.BooleanField(default=False)
    blocked = models.BooleanField(default=False)
    anonymous = models.BooleanField(default=False)
    user = models.OneToOneField(auth_models.User)

【讨论】:

  • 我知道有几种额外的方法可以处理这个问题,但让我感到困惑的是 Django 处理继承的方式。如果我已经提供了指向已经创建和初始化的父对象的指针,那么在创建子对象后使用空字段更新基本模型的原因是什么?
  • @Ricardo 这是因为当您调用 create 时,它会创建一个“新的”UserProfile 模型。您传入的 user_ptr 只是在该新模型上设置 OneToOneField。除非您明确执行,否则新的 UserProfile 模型不会设置任何用户属性。保存后,这些用户属性都设置为空。
猜你喜欢
  • 2023-03-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-11-25
  • 1970-01-01
  • 2012-04-11
相关资源
最近更新 更多