Django:为什么要创建一个 OneToOne 到 UserProfile,而不是子类化 auth.User?
注意:如果您想通过告诉我您不喜欢 django.contrib.auth 来“回答”这个问题,请继续。那不会有帮助。我很清楚关于这个问题的意见的范围和强度。
现在的问题是:
惯例是创建一个模型 UserProfile,其中包含 OneToOne 到 User。
在我能想到的各种方式中,一种更高效和有效的方法是将 User 子类化为一个打算用于系统中每个人的类 - 一个名为 Person(User) 的类。
我还没有看到一个连贯的解释为什么前者是常规的而后者被视为黑客。不久前,我改用了 OneToOne 方法以获得使用 get_profile() 的能力,但从那以后我就后悔了。我正在考虑切换回来,除非我能够理解这种方法的优点。
Note: If you are tempted to 'answer' this question by telling me that you don't like django.contrib.auth, please move on. That will not be helpful. I am well aware of the range and strength of opinions on this matter.
Now, the question:
The convention is to create a model, UserProfile, with a OneToOne to User.
In every way I can think of, a more efficient and effective approach is to subclass User to a class that one intends to use for every human in the system - a class called, say, Person(User).
I have not seen a coherent explanation of why the former is conventional and the latter is regarded as a hack. A while ago, I changed over to the OneToOne approach so as to gain the ability to use get_profile() and I have regretted it ever since. I'm thinking of switching back unless I can be made to understand the advantage of this approach.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
您确实意识到,模型子类化是通过底层的 OneToOne 关系实现的,不是吗?事实上,就效率而言,我看不出这两种方法有什么区别。
在我看来,现有具体模型的子类化是一种令人讨厌的黑客行为,应该尽可能避免。它涉及隐藏数据库关系,以便不清楚何时执行额外的数据库访问。显式显示关系并在必要时显式访问它们会更加清晰。
现在,我喜欢的第三种选择是创建一个全新的用户模型,以及一个返回新模型实例而不是默认模型实例的自定义身份验证后端。创建后端只需要定义几个简单的方法,因此非常容易做到。
You do realise, don't you, that model subclassing is implemented by means of a OneToOne relationship under the hood? In fact, as far as efficiency is concerned, I cannot see any difference at all between these two methods.
Subclassing of existing concrete models is, in my opinion, a nasty hack that should be avoided if at all possible. It involves hiding a database relationship so that it is unclear when extra db access is performed. It's much clearer to show the relationships explicitly, and access them explicitly where necessary.
Now, a third alternative which I do like is to create a completely new User model, along with a custom authentication backend that returns instances of the new model instead of the default one. Creating a backend only involves defining a couple of simple methods, so it's very easy to do.
从来没有一个真正好的解释,至少从“官方”来源来看,为什么在实践中,子类化 User 不如拥有 UserProfile 有用。
然而,我有几个原因,是在我自己决定对 User 进行子类化是“可行的方法”之后出现的。
django.contrib.auth.models.User
。大多数情况下这是可以的,除非该代码正在获取 User 对象。因为我们是一个子类,所以任何仅使用 User 对象的代码都应该没问题。因此,您可能会说,“我的项目将只有一个 User 子类”。我就是这么想的。现在我们有三个,加上普通用户,可能还有第四个。 需求发生变化,必须更改大量代码来处理这种情况并不是很有趣。
注意:最近 django-developers 上有很多关于更好地修复与 contrib.auth User 模型相关的问题的讨论。
There's never really been a good explanation, at least from "official" sources as to why, in practice, subclassing User is less useful than having a UserProfile.
However, I have a couple of reasons, that came up after I had decided myself that subclassing User was "the way to go".
django.contrib.auth.models.User
. Mostly this will be okay, unless that code is fetching User objects. Because we are a subclass, any code just using our User objects should be fine.So, you may say, "my project will only ever have the one User subclass". That's what I thought. Now we have three, plus regular Users, and possibly a fourth. Requirements change, having to change heaps of code to deal with that is not much fun.
note: There has been quite a lot of discussion on django-developers recently about a better fix to the issues related to the contrib.auth User model.
继承User模型是不是更加高效有效呢?我不明白为什么,但我想读一下你的论点。 IMNSHO,模型继承一直是一个痛苦。
然而,这可能无法回答您的问题,但我对 Will Hardy 在此片段<中提出的解决方案非常满意/a>.通过利用信号,它会自动为每个新用户创建一个新的用户配置文件。
该链接不太可能消失,但这是我的代码的略有不同的版本:
当然,任何功劳都归于威尔·哈迪(Will Hardy)。
Is it more efficient and effective to inherit the User model? I don't see why, but I'd like to read your arguments. IMNSHO, model inheritance has always been a pain.
Yet, this may not answer your question, but I'm quite satisfied with the solution proposed by Will Hardy in this snippet. By taking advantage of signals, it automatically creates a new user profile for every new user.
The link is unlikely to disappear, but here's my slightly different version of his code:
Of course, any credit goes to Will Hardy.
如果您只有一种类型的用户,例如任何社交媒体网站 Facebook 或 Instagram,那么请选择继承。
如果您的应用程序有不同类型的用户,例如帐户、学生、教师、库存经理,则选择 oneToone 关系。
If you are having just one type of user, like any social media site facebook or Instagram then go for inheritance.
If your application has different type of users, like accounts, student, teacher, inventory manager then go for oneToone relationship.