【问题标题】:What's a clean way to adorn Django models with request-specific attributes?用特定于请求的属性来装饰 Django 模型的干净方法是什么?
【发布时间】:2010-02-07 00:06:34
【问题描述】:

我正在将 User 对象序列化为 JSON,我想在 JSON 响应中指出序列化的用户是否与发出请求的用户是朋友。

我在我的 User 模型中添加了一个 to_dict() 方法,该方法执行序列化对象所需的预处理——这将是一个添加表示友谊的属性的好地方,但由于 User.to_dict() 没有'无权访问请求对象,我似乎无法在那里进行。

在视图中执行此操作很容易,但我不想在其他视图中重复该代码。我想将用户对象“升级”为请求感知用户对象。

django.contrib.auth 用户模型有一个 is_authenticated 属性,它实际上是请求的属性而不是模型的属性——该属性仅在特定 Web 请求的上下文中才有意义。

就好像我应该将 request.user 替换为 RequestUser 的实例,这是一个接受 User 和 Request 并添加特定于请求的属性的新类。有什么干净的方法可以做到这一点?

【问题讨论】:

    标签: django json request


    【解决方案1】:

    这并不能真正回答您的问题,但您确定要通过 User 上的方法处理友谊吗?我这样说是因为:

    1. 围绕友谊的逻辑可能在另一个应用程序中,因此您可能希望明确调用该应用程序中定义的函数;
    2. 友谊几乎总是对称关系,因此对 User 使用方法会导致冗余 (a.is_friend_with(b) == b.is_friends_with(a))。例如,如果您稍后想要缓存调用的结果,那么定义一个简单地接受用户对象作为任意顺序参数的函数是有意义的;并且,
    3. 您可能不想对 HttpRequest 或 User 做任何花哨的事情,因为这可能会使其他开发人员感到困惑。

    我的方法是在代表友谊的任何模型上定义一个管理器方法,并将用户显式传递给它,如下所示:Friendship.objects.are_friends(other_user, request.user)

    【讨论】:

    • 谢谢,很重要。为什么是管理器方法而不是 Friendship 上的类方法,即 Friendship.are_friends(a, b)?
    • 我已经为这个问题添加了更多细节——想听听你的想法。谢谢!
    • 类方法也很有意义。与类之外的实用函数一样。我正在考虑一个管理器方法,因为您可能希望将它链接在其他管理器方法(例如过滤器)之后以在更有限的查询集中检查 are_friends,但也许这不是必要/可取的。
    【解决方案2】:

    你可以创建一个 auth.User 的代理模型并在那里添加你的 is_friend 方法。 http://docs.djangoproject.com/en/dev/topics/db/models/#proxy-model-managers

    至于 is_authenticated 方法,它比你想象的要简单一些。如果用户未登录,用户上下文处理器会提供一种特殊类型的用户,即 AnonymousUser。调用 is_authenticated 时,此类始终返回 False。同样,当调用 is_authenticated 时,常规 User 类总是返回 True。

    简而言之,不要担心请求对象。如果当前用户未登录,则视图中可用的用户变量将使用 AnonymousUser 类,并且找不到您的 is_friends 方法。

    【讨论】:

    • 代理模型听起来是对 User 进行子类化的好方法,谢谢。
    猜你喜欢
    • 2018-11-07
    • 2013-10-08
    • 2013-02-16
    • 1970-01-01
    • 2018-10-03
    • 1970-01-01
    • 2011-08-22
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多