现在的位置: 首页 > 综合 > 正文

Django技巧:改变Admin中显示的应用(app)名称

2013年02月27日 ⁄ 综合 ⁄ 共 2010字 ⁄ 字号 评论关闭

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。所以强烈不建议本文的做法。

抱歉!评论已关闭.