注意:如果你想通过告诉我你不喜欢django.contrib.auth来回答这个问题,请继续。这没有用。我很清楚这个问题的范围和意见。
现在,问题是:
惯例是使用OneToOne创建一个模型UserProfile。
在我能想到的各种方式中,一种更有效和更有效的方法是将User子类化为一个打算用于系统中每个人的类 - 一个名为Person(User)的类。
我没有看到为什么前者是传统的而后者被视为黑客的连贯解释。不久之前,我改用了OneToOne方法,以便获得使用get_profile()的能力,从此我就后悔了。我正在考虑转回去,除非我能够理解这种方法的优势。
答案 0 :(得分:4)
你知道,不是吗,那个模型子类化是通过引擎盖下的OneToOne关系来实现的吗?事实上,就效率而言,我看不出这两种方法之间存在任何差异。
在我看来,现有混凝土模型的子类化是一个讨厌的黑客,如果可能的话应该避免。它涉及隐藏数据库关系,以便不清楚何时执行额外的数据库访问。明确地显示关系并在必要时明确地访问它们会更清楚。
现在,我喜欢的第三种选择是创建一个全新的User模型,以及一个自定义身份验证后端,它返回新模型的实例而不是默认模型的实例。创建后端只涉及定义几个简单的方法,因此很容易做到。
答案 1 :(得分:2)
至少在“官方”消息来源中,从来没有真正得到过很好的解释,至于为什么在实践中,子类化用户不如拥有UserProfile有用。
然而,我有几个原因,在我决定自己将子类化为“走的路”之后出现了。
django.contrib.auth.models.User
。除非该代码正在获取用户对象,否则这一切都会没问题。因为我们是一个子类,所以只使用我们的User对象的代码应该没问题。所以,你可能会说,“我的项目只会拥有一个用户子类”。那正是我所想。现在我们有三个,加上常规用户,可能还有第四个。 需求更改,不得不更改大量代码来处理这个问题并不是很有趣。
注意:最近有很多关于django-developers关于更好地解决与contrib.auth用户模型相关问题的讨论。
答案 2 :(得分:0)
继承User模型是否更有效率?我不明白为什么,但我想读你的论点。 IMNSHO,模型继承一直是一种痛苦。
然而,这可能无法解答您的问题,但我对Will Hardy在this snippet中提出的解决方案非常满意。通过利用信号,它会自动为每个新用户创建一个新的用户配置文件。
链接不太可能消失,但这是我的代码略有不同的版本:
from django.contrib.auth.models import User
from django.db import models
from django.db.models.signals import post_save
from django.utils.translation import ugettext_lazy as _
class AuthUserProfileModelBase(models.base.ModelBase):
# _prepare is not part of the public API and may change
def _prepare(self):
super(AuthUserProfileModelBase, self)._prepare()
def on_save(sender, instance, created, **kwargs):
if created:
self.objects.create(user=instance)
# Automatically link profile when a new user is created
post_save.connect(on_save, sender=User, weak=False)
# Every profile model must inherit this class
class AuthUserProfileModel(models.Model):
class Meta:
abstract = True
__metaclass__ = AuthUserProfileModelBase
user = models.OneToOneField(User, db_column='auth_user_id',
primary_key=True, parent_link=True)
# The actual profile model
class Profile(AuthUserProfileModel):
class Meta:
app_label = 'some_app_label'
db_table = 'auth_user_profile'
managed = True
language = models.CharField(_('language'), max_length=5, default='en')
当然,任何功劳都归功于Will Hardy。