假设我有两种类型的用户:简短和长。
当简要用户登录时,他应该只能看到最近的10个项目。当 long 用户登录时,他应该会看到最近的30个项目。否则他们非常相似。
我相信我可以使用Django Managers来实现这样的东西:
class Item(models.Model):
name = models.CharField(max_length=200)
date = models.DateField()
class BriefItemManager(models.Manager):
def get_query_set(self):
return super(BriefItemManager, self).get_query_set().order_by('date')[:10]
class LongItemManager(models.Manager):
def get_query_set(self):
return super(LongItemManager, self).get_query_set().order_by('date')[:30]
我正在考虑猴子修补项目,也许使用中间件,以便其余代码无视用户是简要还是 。在主代码启动时,项的 .objects 管理器将被设置为 BriefItemManager 或 LongItemManager 英寸
if user_type(request.user) == 'brief':
Item.objects = BriefItemManager()
else:
Item.objects = LongItemManager()
问题:
答案 0 :(得分:2)
你不希望monkeypatch那个sucker,因为一旦Item
类型被创建,它的状态就会在线程之间共享,其中包括默认的管理器。即使当前请求的用户属于long
类型,也可以检索10个项目,因为模型管理器上存在线程争用。 (请参阅包django.db.models.base
)中的ModelBase
在你的情况下,你会想要明确你做的是什么。这是我最好的猜测:
class ItemManager(models.Manager):
def latest_for_user_type(user_type):
limit = user_type=='brief' and 10 or user_type=='long' and 30
return self.get_query_set().order_by('date')[:limit]
class Item(models.Model)
# ...
objects = ItemManager()
# views.py
class LatestItemListView(ListView):
def get_query_set(self):
return Item.objects.latest_for_user_type(
user_type=user_type(self.request.user)
)
您可能希望在user_type()
中实施ItemManager
逻辑...您甚至可能希望将其重构为latest_for_user(user=None, user_type=None)
。这只是基本思想,还有其他方法,如代理类,是覆盖模型管理器的理想选择(唯一的方法)。
管理者是实施集合操作的正确方法。