【问题标题】:create django user based on existing model object基于现有模型对象创建 django 用户
【发布时间】:2021-07-26 05:37:33
【问题描述】:

我正在开发 Property Management django 应用程序,其中我的基本模型是 租户,包含所有基本信息,如姓名、姓氏、电子邮件等。愿意的租户将能够创建 用户帐户 以便他们可以登录并预订健身房/电影院,但并非所有租户都需要拥有用户帐户。我的问题是:

如何根据现有租户对象创建新用户帐户?显然,用户将拥有 Tenant ForeignKey,但如何将 Tenant.name、Tenant.surname 等提取到我的用户模型中的多个字段?

ForeignKey 只给了我对对象的引用,但我可以在创建新用户期间以某种方式访问​​该对象的某些字段,因此我确保 Tenant.email 与 user.email 相同?

编辑

tenancy = (('Tenant', 'Tenant'),('Owner', 'Owner'), ('Other', 'Other'))

class Tenant(models.Model):

    name          = models.CharField(max_length=15, null=True, blank=False)
    surname       = models.CharField(max_length=30, null=True, blank=False)
    email         = models.EmailField(max_length=50, unique=True)
    phone_number  = models.CharField(max_length=20, null=True, blank=True, unique=True)
    flat          = models.ForeignKey(Flat, on_delete=models.PROTECT)
    status        = models.CharField(max_length=10, choices=tenancy, null=True, blank=False)
    stay_length   = models.CharField(max_length=20, null=True, blank=False)
    pet_licence   = models.CharField(max_length=20, null=True, blank=False)
    additional_notes= models.TextField(max_length=300, blank=True)
    date_added    = models.DateField(auto_now_add=True, null=True)
    moved_out     = models.BooleanField(default=False)
    date_moved_out= models.DateField(auto_now_add=False, null=True)

    class Meta:
        unique_together = ('name', 'surname',)


    def __str__(self):
        return f'{self.name} {self.surname}' 

现在我想创建用户帐户模型,其中 name、surname、email、phone_number 和 flat 将是 Tenant 模型的 ForeignKeys。是否有可能让 1 个对象中的 4 个 ForeignKeys 填充新模型?

我尝试过使用 ForeignKey.limit_choices_to、ForeignKey.related_name、ForeignKey.to_field(这很接近,但与相关的字段必须是唯一的,这对我的情况不起作用)但一切都会出错。我只是想知道是否有可能将 1 个对象的 1 个以上的 ForeignKey 定向到新模型对象的多个不同字段。

【问题讨论】:

  • 什么是租户?
  • 您能否展示您的模型,以及到目前为止您为解决此问题所做的尝试?
  • JoranBeasley 租户是租用公寓、公寓或任何其他地方居住的人。 @bdbd 我在编辑中回答,如果你有机会看看。谢谢!
  • 您是否考虑过one-to-one 与用户模型的关系可以为空?
  • @bdbd 我不能让用户为 null - 每个用户都必须被分配给具有相同字段的确切 1 个租户,但并非每个租户都必须成为用户。 null=True 的 1to1 并不能解决如何使用 Tenant 的更多字段并将它们分配给用户的更多字段的问题。

标签: python django django-models


【解决方案1】:

我会以外键在Tenant 中而不是User 的方式处理它,并将其定义为可为空的one-to-one。这样你就可以让你的 User 模型没有外键:

class Tenant(models.Model):
    user = models.OneToOneField(
        User,
        related_name='tenant',
        on_delete=models.CASCADE,
        null=True,
        blank=True,
        default=None,
    )

然后要创建相关用户,您可以在 Tenant 模型中添加一个方法,如下所示:

class Tenant(models.Model):
    ...
    def create_user(self):
        if not self.user:
            user = User.objects.create(
                first_name=self.name,
                last_name=self.surname,
                ...
            )
            self.user = user
            self.save()

查看文档here 中的示例。

【讨论】:

  • 是的!我刚试过,效果很好,谢谢。它实现了我的主要目标——我可以完全控制所有用户字段,并确保它们与后端而不是前端的租户相同(因此管理员不会弄乱它们)。用户模型不干扰租户,仅在需要时使用。
【解决方案2】:

您可以使用 to_field 为另一个模型的非 pk 字段创建 fkey,但是,这些字段需要具有唯一约束(即 unique=True) - 这对于姓名/姓氏来说似乎不太可能。

听起来您想要从用户模型到租户模型字段的透明访问,这是不可能的。

您可以创建从用户到租户的 fkey:

class User(models.Model):
    tenant = models.OneToOneField(Tenant, null=True, blank=True, related_name='user')
    ...

然后使用

访问字段
user = User.objects.get(...)
user.tenant.surname

要保持字段同步,您可以覆盖 save() 方法:

class Tenant(...)
    ...
    def save(self, *args, **kwargs):
        if self.user:
             self.user.last_name = self.surname
             ...
             self.user.save()
        super().save(*args, **kwargs)

aside:null=True 表示数据库应该允许字段为空,blank=True 表示在管理界面中该字段可以为空。在大多数情况下,您可能应该拥有null=True, blank=True

【讨论】:

  • 谢谢,我会试试这个。您能否用简单的术语解释一下 def save() 在类 Tenant 中究竟会做什么以及我会在什么时候使用它?赞赏!
  • save() 将在租户对象被保存时被调用,并且它应该将任何更新信息复制到相应的用户字段。
  • 好的,谢谢,我将试用此解决方案。我想让一切都万无一失,这样即使管理员也不能搞砸,这就是为什么自动导入会更容易解决(如果存在的话!),但我会尝试在视图和前端处理所有这些。感谢您的帮助!
  • 几乎所有模型被更改的情况下都会调用 save() 函数,包括来自管理员,即如果有人在管理员中更改租户数据,save() 函数将确保用户对象自动更新。
  • 好建议!我实现了,谢谢,总是会让事情更整洁。
猜你喜欢
  • 1970-01-01
  • 2011-07-01
  • 2021-01-14
  • 1970-01-01
  • 2011-01-09
  • 2015-04-25
  • 2013-12-31
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多