自定义用户类在django中断应用程序?

时间:2009-05-28 20:53:57

标签: django authentication django-models

假设我已正确分类用户模型(CustomUser)(如下所述:http://scottbarnham.com/blog/2008/08/21/extending-the-django-user-model-with-inheritance/

并安装了评论应用。

在我写的模板中访问评论的用户:

{{comment.user}} # which provides User, not my CustomUser

因此,

{{comment.user.CustomProperty}} #does not work.

我该如何解决它?

3 个答案:

答案 0 :(得分:2)

正如你在该帖子的评论中所看到的那样,它仍然存在争议性的讨论,最好的方法是什么。

我也是通过子类化尝试过的,但我遇到了很多问题,而using profiles 对我来说非常适合。

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()

编辑:为什么user_profiles优雅:

我们假设,我们正在编写一个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)
    ....
    ....

这导致

  • 具有大量零值的数据行
  • 棘手的 what-if-then 验证
  • 不可能,拥有更多同一服务的帐户

现在让我们用user_profiles

来做
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()

结果:

  • 可在需要时创建User_profiles
  • db没有被零值淹没
  • n相同类型的配置文件可以分配给一个用户
  • 验证很容易

这可能会导致模板中的语法更加含糊,但我们可以在views / template_tags中自由选择一些快捷方式,或者使用{% with ... %}来根据需要调整它。

答案 1 :(得分:2)

来自ForeignKey的{​​{1}}是django的内置comments.Comment对象,因此查询User会为您提供父对象(即:comment.user }模型)。但是,django继承确实提供了从超类获取子类版本的方法:

User

然后允许你这样做:

{{ comment.user.customeruser }}

我碰巧认为这是Django继承实现中的一个弱点,因为它并不能完全反映Python中对象继承所期望的行为,但至少有一种解决方法。由于我很难急于提交我的正确行为版本的补丁,我不能抱怨: - )


我同意Carl Meyer的观点:在不改变父模型的db表的情况下自动获取子类可能会很昂贵,并且从父类查询返回子类的实例将与Django承诺查询集返回模型不一致在哪个查询集上运行。

然而,我仍然在实践中发现,Django的继承有时会导致一些尴尬的额外步骤。从0.91开始使用Django,并且知道解决对象关系映射问题的所有不同策略都有权衡,我很高兴现在在Django中继承,并且觉得当前的实现非常好...所以我想讨厌我原来的答案被认为是对项目的轻微反对。

因此,我想我会编辑这个答案,链接到Carl自己在解决方案上提供的答案,如果你不知道子类是什么类型的话:How do I access the child classes of an object in Django without knowing the name of the child class?。他在那里提供了使用ContentType框架的建议。还有一些间接涉及,但工具包中有一个很好的,可推广的选项。

答案 2 :(得分:1)

我认为没有办法绕过它,因为如你所说,comment.userUser,而不是CustomUser

请参阅http://docs.djangoproject.com/en/dev/topics/db/models/#proxy-models

  

QUERYSS仍然返回要求的型号
  每当你查询User对象时,就没有办法让Django返回一个MyUser对象。 User对象的查询集将返回这些类型的对象。代理对象的重点是依赖于原始用户的代码将使用这些代码,并且您自己的代码可以使用您包含的扩展(无论如何其他代码都不依赖)。它不是用你自己创造的东西替换用户(或任何其他)模型的方法。

也许在这种情况下,使用UserProfile的旧方式会是更好的选择吗?

对不起,如果我帮不了多。