2011-12-30 31 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)