django中的自定义用户类是否中断应用程序?
假设我已经正确地对用户模型(CustomUser)进行了子类化(如下所述:) 并安装了评论应用程序 要访问模板中注释的用户,请执行以下操作:django中的自定义用户类是否中断应用程序?,django,authentication,django-models,Django,Authentication,Django Models,假设我已经正确地对用户模型(CustomUser)进行了子类化(如下所述:) 并安装了评论应用程序 要访问模板中注释的用户,请执行以下操作: {{comment.user}} # which provides User, not my CustomUser 因此 {{comment.user.CustomProperty}} #does not work. 我怎样才能解决它呢?我认为没有办法解决它,因为正如你所说,注释。用户是用户,而不是自定义用户 见: 查询集仍然返回请求的模型 无论何时查
{{comment.user}} # which provides User, not my CustomUser
因此
{{comment.user.CustomProperty}} #does not work.
我怎样才能解决它呢?我认为没有办法解决它,因为正如你所说,
注释。用户
是用户
,而不是自定义用户
见:
查询集仍然返回请求的模型无论何时查询用户对象,Django都无法返回(比如)MyUser对象。用户对象的查询集将返回这些类型的对象。代理对象的全部要点是依赖于原始用户的代码将使用这些对象,并且您自己的代码可以使用您包含的扩展(其他代码无论如何都不依赖这些扩展)。这不是一种用你自己创造的东西来替代用户(或任何其他)模型的方法 在这种情况下,使用
UserProfile
的旧方法可能是更好的选择
如果我帮不上什么忙,很抱歉。正如你在那篇文章的评论中所看到的,它仍然是有争议的讨论,什么是最好的方式 我也尝试过子类化,但我遇到了很多问题,而这对我来说是完美的
class IRCUser(models.Model):
user = models.ForeignKey(User, unique=True)
name = models.CharField(max_length=100, blank= True, null = True )
friends = models.ManyToManyField("IRCUser", blank= True, null = True)
dataRecieved= models.BooleanField(default=False)
创建IRCUser的工作原理如下:
>>> IRCUser(user = User.objects.get(username='Kermit')).save()
编辑:为什么用户配置文件优雅:
让我们假设,我们正在编写一个webapp,它将作为一个多协议聊天。用户可以在ICQ、MSN、Jabber、FaceBook、Google Talk等网站上提供自己的账户
我们可以通过继承自由创建一个自定义用户类,该类将保存所有附加信息
class CustomUser(User):
irc_username = models.CharField(blank=True, null=True)
irc_password = models.PasswordField(blank=True, null=True)
msn_username = models.CharField(blank=True, null=True)
msn_password = models.PasswordField(blank=True, null=True)
fb_username = models.CharField(blank=True, null=True)
fb_password = models.PasswordField(blank=True, null=True)
gt_username = models.CharField(blank=True, null=True)
gt_password = models.PasswordField(blank=True, null=True)
....
....
这导致了
- 包含大量零值的数据行
- 棘手的假设验证
- 不可能在同一服务中拥有多个帐户
class IRCProfile(models.Model):
user = models.ForeignKey(User, unique=True, related_name='ircprofile')
username = models.CharField()
password = models.PasswordField()
class MSNProfile(models.Model):
user = models.ForeignKey(User, unique=True, related_name='msnprofile')
username = models.CharField()
password = models.PasswordField()
class FBProfile(models.Model):
user = models.ForeignKey(User, unique=True, related_name='fbprofile')
username = models.CharField()
password = models.PasswordField()
结果是:
- 用户配置文件可以在需要时创建
- 数据库没有被零值淹没
- n相同类型的配置文件可以分配给一个用户
- 验证很容易
这可能会导致模板中的语法更加晦涩,但我们可以在视图/模板标签中自由设置一些快捷方式,或者使用
{%with…%}
来根据需要对其进行调味。来自注释的外键
。注释
是django的内置用户
对象,因此,查询comment.user
将为您提供父对象(即:基本user
模型)。但是,django继承确实提供了一种从超类获取子类版本的方法:
{{ comment.user.customeruser }}
这将允许您执行以下操作:
{{ comment.user.customeruser.customproperty }}
我碰巧认为这是Django的继承实现中的一个弱点,因为它并不完全反映您通常期望从Python中的对象继承中获得的行为,但至少有一个解决方法。由于我几乎没有急于提交一个带有我的正确行为版本的补丁,我不能抱怨:-)
我同意Carl Meyer的评论:在不改变父模型的db表的情况下自动获取子类可能代价高昂,并且从父类查询返回子类的实例与Django关于queryset返回运行queryset的模型的承诺不一致 然而,我仍然发现在实践中,Django的继承有时会导致一些尴尬的额外步骤。从0.91开始使用Django,并且知道解决对象关系映射问题的所有不同策略都有折衷之处,我很高兴现在在Django中实现了继承,并且觉得当前的实现非常出色。。。所以我不希望我最初的回答被理解为对这个项目的轻蔑
因此,我想我会编辑这个答案,以链接到Carl自己在解决方案中提供的答案,如果您不知道子类是什么类型:。他在那里提供了使用ContentType框架的建议。仍然涉及一些间接操作,但这是工具箱中一个好的、可推广的选项。我使用了好的旧用户配置文件,但当用户配置文件本身有多对多关系(如朋友)时,事情变得不雅观了。看看这个,这不是很“可爱”吗?:friend=my_user.get_profile()。跟踪了_用户[0]。user——因此,我对user进行了子类化;但现在看来有些应用程序对我来说是不可用的。我可以肯定地看到它会很快变得一团糟!正如我在Arnaud的帖子上评论的那样,我不喜欢userprofile本身有多对多关系的情况。用户和用户之间的关系是userprofile和userprofile之间的关系。不优雅的IMO。请参见我的编辑,以获取一个示例,为什么用户_配置文件可以非常优雅这确实没有“反映出您期望从Python中的对象继承中获得的行为”,但有很好的理由可以实现它,我想如果你尝试写一个补丁,你会发现:-)我假设你想要的行为是让一个对象自动成为“叶”子类;问题在于,对于需要多个昂贵查询才能计算出的大型继承树。或者您必须在父模型上存储类型信息,但是必须修改父模型会导致许多继承用例的死亡。Carl,这是一个很好的补充信息。我在另一个问题的ContentTypes框架的基础上添加了一个链接到您的一个答案。回答得好。我同意Django的继承会导致“尴尬的额外步骤”,只是尴尬是问题域的固有特性,而不是特定的实现。将对象继承映射到关系数据库是一件很麻烦的事情,无论您如何分割它。