Lincoln Looper的同事Martin Mahner在如何在Django的管理中使用代理模型來分離員工和用戶帳戶. 在客戶機項目中,我們經常需要這樣的功能,但是人們通常不會考慮使用代理模型來實現這個功能。這是我們最近遇到的另一個場景,它們非常有用。
背景
代理模型在django1.1中引入。並將它們與官方文獻進行對比,描述它們的用法。官方文檔沒有明確指出的一個事實是django不允許在同一個模型中注冊多個modeladmin。這就是代理模型可以出手相救的地方。
例子
考慮一個新聞編輯室應用程序,其中的文章必須分為幾個部分:
#models.py from django.db import models class Section(models.Model) name = models.CharField(max_length=90) slug = models.SlugField(max_length=90) # ... More fields class Article(models.Model): section = models.ForeignKey('Section', null=True, blank=True) # ... more fields class ReviewArticle(Article): class Meta: proxy=True
在這里,ReviewArticle
只是一個Python構造,它不會更改底層數據庫結構。它只是提供了一種在同一模型/表中邏輯隔離對象的方法。
代理模型的好處
代理模型的典型用例是通過更改模型的默認管理器或類方法來覆蓋模型的Python行為。正如Martin指出的,代理模型非常適合於在管理中“偽造”內容分離。此外,還會為代理模型自動設置一組新的權限:可以添加、可以更改、可以刪除。
這使我們能夠為真正位於同一數據庫表中的對象呈現不同的用戶體驗。在上面的例子中,我們可以給管理員一個編輯評論文章的地方,這些評論文章是專門為評論文章的需要而定制的,盡管實際上它們是相同的數據模型。
ModelAdmin Example
下面是一個在Django管理中使用代理模型的簡單示例
from django.contrib import admin from myapp.models import Article, ReviewArticle class ArticleAdmin(admin.ModelAdmin): pass class ReviewArticleAdmin(admin.ModelAdmin): pass def queryset(self, request): return self.model.objects.filter(section__name="reviews") admin.site.register(Article, ArticleAdmin) admin.site.register(ReviewArticle, ReviewArticleAdmin)
現在修改你的代理模型ReviewArticle
對象保存在“審閱”部分:
class ReviewArticle(Article): class Meta: proxy=True def save(self, *args, **kwargs): self.section = Section.objects.get(name='reviews') super(ReviewArticle, self).save(*args, **kwargs)
這是一個簡單的示例,但是使用Django管理中提供的定制選項,您可以向用戶呈現一個非常不同的界面。你可以在ModelAdmin
,包括:
list_filter
list_display
search_fields
inlines