2011-12-30 36 views
0

我正在创建一个将DVD/BD存储到数据库的基于Django的电影集合。应用程序将这些电影保存到存档。用户可以拥有一个档案,但档案可以被多个人使用(例如,家庭成员可以共享相同的档案)。而同样与Django模型:根据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()可以完成这项工作,但是有没有一种方法可以完成过滤功能,以便所有视图都只执行一次?用中间件?还是装饰者?

回答

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)