[原]Django技巧:改变Admin中显示的应用(app)名称
Django的Admin提供了强大的功能,很多人可能会基于Admin开发自己的应用。
在Admin默认的管理界面中,Model类的显示名称可以通过国际化的方法来改变,其实app的名称也可以自己指定,你甚至可将同一个应用下的Model类分配到不同的app中去分组,如下图:
以《Django实战》中的Model类为例,可以这样指定Order类显示的应用名称:
class Order(models.Model): name = models.CharField(max_length=50) address = models.TextField() email = models.EmailField() class Meta: verbose_name = "订单" verbose_name_plural = "订单" app_label = u"我的应用"
你甚至可以将同一app下的另一个Model类:Product指定到另一个应用下面:
class Product(models.Model): title = models.CharField(max_length=100,unique=True) description = models.TextField() image_url = models.URLField(max_length=200) price = models.DecimalField(max_digits=8,decimal_places=2) date_available = models.DateField() orders = models.ManyToManyField(Order,through='LineItem') class Meta: verbose_name = "产品" verbose_name_plural = "产品" app_label = u"我的应用1"
这里面需要注意的是,因为Product到Order的many-to-many关系是通过LineItem类关联的,所以必须将LineItem的app_label设置成与Product的相同:
class LineItem(models.Model): product = models.ForeignKey(Product) order = models.ForeignKey(Order) unit_price = models.DecimalField(max_digits=8,decimal_places=2) quantity = models.IntegerField() class Meta: verbose_name = "订单项" verbose_name_plural = "订单项" app_label = u"我的应用1"否则会出现错误:我的应用1.product: 'orders' specifies an m2m relation through model LineItem, which has not been installed
也就是说,如果Order和Product都指定了ManyToMany(through)关联,则这三个类(Order, Product, LineItem)的app_label必须相同。
此问题来自hbjsfeng的提问,在翻看Django的源代码时偶然发现解决办法。不敢独享,所以发布出来。欢迎访问Django专栏,并互相交流,如转载请加链接:http://blog.csdn.net/thinkinside/article/details/7255707
根据1楼的评论做一下补充:
这样做确实不是一个好的做法,会破坏Django内部的逻辑,此时在Admin界面操作模型类会报“找不到表”的错误。因为Django的Model会按照[app_label]_[model_name]的格式去找数据库表,而我们改了app_label,当然找不到。权宜的办法是再增加一个Meta属性:db_table。比如:
class Order(models.Model): name = models.CharField(max_length=50) address = models.TextField() email = models.EmailField() class Meta: verbose_name = "订单" verbose_name_plural = "订单" app_label = u"我的应用" db_table = 'depotapp_order'这样在管理界面就可以操作了。但是如果是一开始就这样创建Model类,在syncdb时不会创建任何数据库表。除非你先注释掉app_label,syncdb后再去掉注释。
其实app_label的原本意图是当你在标准的app/models.py之外(比如app的子模块中)创建Model类时,通过指定app_label来告诉Django其应该属于的app,而不是指定到一个根本不存在的app。所以强烈不建议本文的做法。
- 上一篇:[转]Python之禅
- 下一篇:[原]深入Django(2):自定义ORM