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