我正在创建一个基于Django的电影集合,将DVD / BD存储到数据库中。应用程序将这些电影保存到存档。用户可以拥有一个存档,但存档可以由多个人使用(例如,家庭成员可以共享相同的存档)。和Django模型一样:
class UserProfile(models.Model):
user = models.ForeignKey(User, unique=True)
archive = models.ForeignKey(Archive, blank=True, null=True)
class Archive(models.Model):
name = models.CharField(max_length=200)
class Movie(models.Model):
archive = models.ForeignKey(Archive)
title = models.CharField(max_length=200, null=True, blank=True)
确保用户只能看到属于用户档案的电影和其他信息的最佳做法是什么?
当然filter()可以完成这项工作,但是有没有办法进行过滤,所以只对所有视图进行一次?有中间件吗?还是装饰师?
答案 0 :(得分:2)
如果您的网址风格只有/movies/some-movie/
,@ jknupp的答案可能是您最好的选择,但如果您正在做更像/user/some-user/movies/some-movie/
的事情。视图的责任是确保只显示属于用户的电影。
在任何一种情况下,它仍然是视图的责任,以某种形式或其他形式。这是MVC设计模式的自然划分(Django确实利用了它,尽管很松散)。该模型不知道,也不应该知道有关用户的任何信息。它的目的是简单地允许在每个场景中存储和检索数据。但是,该视图确实了解用户,因为它正在处理请求,因此处理会话,因此任何特定于会话的处理(例如权限和身份验证)都属于那里。
然而,这并不是说您仍然无法将工作卸载到模型中。我的建议是创建一个自定义管理器方法,过滤特定用户的项目,然后您可以在视图中使用这些项目。例如:
class MovieQuerySet(models.query.QuerySet):
def allowed_for_user(self, user):
return self.filter(archive__user=user)
class MovieManager(models.Manager):
use_for_related_fields = True
def get_query_set(self):
return MovieQuerySet(self.model)
def allowed_for_user(self, *args, **kwargs):
return self.get_query_set().allowed_for_user(*args, **kwargs)
class Movie(models.Model):
...
objects = MovieManager()
当然,该管理器方法相当简单,但仍需要知道您必须通过影片的归档外键查询用户,并且该类型的知识是模型/管理器的范围。然后在你看来,你只需要这样做:
movies = Movie.objects.allowed_for_user(request.user)
答案 1 :(得分:0)
看看permission-required decorator.这可能正是你所需要的。