Django:反向OneToOneField匹配而没有related_name

时间:2019-09-11 03:44:11

标签: django django-models

我有几种代表不同类型的用户个人资料的模型,

class User(models.Model):
  pass

class ProfileA(models.Model):
  user = models.OneToOneField(User, related_name="%(app_label)s_%(class)s_related",)

class ProfileB(models.Model):
  user = models.OneToOneField(User, related_name="%(app_label)s_%(class)s_related",)

class ProfileC(models.Model):
  user = models.OneToOneField(User, related_name="%(app_label)s_%(class)s_related",)

现在,假设我得到了用户实例:如何获得相关的配置文件对象?所有这三个配置文件模型(在我的代码中,我有6个扩展BaseProfile模型的抽象配置文件模型,这是抽象的)都具有其他字段,基本上,我需要从User对象实例中访问整个配置文件对象。

2 个答案:

答案 0 :(得分:1)

应用程序名称是已安装应用程序中应用程序的名称,其中点引用用下划线替换,例如应用程序myapp

user = User.objects.get(...)
a = user.myapp_profilea_related
b = user.myapp_profileb_related
c = user.myapp_profilec_related

您可以通过_meta属性以编程方式获取这些值,该属性是您的Meta子类的实例:

user = User.objects.get(...)
a = getattr(user, f'{ProfileA._meta.app_label}_{ProfileA._meta.model_name}_related')
b = getattr(user, f'{ProfileB._meta.app_label}_{ProfileB._meta.model_name}_related')
c = getattr(user, f'{ProfileC._meta.app_label}_{ProfileC._meta.model_name}_related')

答案 1 :(得分:1)

docs建议使用hasattr,但这种情况可能会有些混乱。

为简化过程,我将基础User模型子类化,然后创建一个自定义方法来获取其自己的配置文件。

例如:

from django.db import models
from django.contrib.auth.models import AbstractUser

class User(AbstractUser):
    def get_profile(self):
        if hasattr(self, 'profile_a'):
            return self.profile_a
        elif hasattr(self, 'profile_b'):
            return self.profile_b
        elif hasattr(self, 'profile_c'):
            return self.profile_c

class ProfileA(models.Model):
    user = models.OneToOneField(User, related_name='profile_a', on_delete=models.CASCADE, primary_key=True)
    name = models.CharField(max_length=45)

class ProfileB(models.Model):
    user = models.OneToOneField(User, related_name='profile_b', on_delete=models.CASCADE, primary_key=True)
    name = models.CharField(max_length=45)

class ProfileC(models.Model):
    user = models.OneToOneField(User, related_name='profile_c', on_delete=models.CASCADE, primary_key=True)
    name = models.CharField(max_length=45)

现在,您可以获取任何User对象的配置文件:

def view(request):
    user = request.user
    print(user.get_profile())

此外,别忘了告诉django,您可以通过在settings.py中添加AUTH_USER_MODEL = 'yourapp.User'来创建新的用户模型。