首页 > django, python > django admin界面处理

django admin界面处理

2009年4月15日 roboter 发表评论 阅读评论

django的admin很强大,可以很方便管理后台数据。近期的一个网站需要处理一堆关联的数据,如果简单使用admin来管理,会碰到一些问题。

情形如下:有A和B两个model

class A(models.Model):
    …

class B(models.Model):
    a = models.ForeignKey(A)
    …

在admin界面中A比较好编辑,在数据量不多的时候,添加B也方便。但是如果A有了几千条数据,添加B的时候要从这么一堆A数据中选择一条,从可用性和系统性能方面来说都是是根本不可能的。于是django admin提供了raw_id_fields字段,ForeignKey字段使用了input编辑框,用户需要手工输入A对象的id即可,或者在弹出的对话框中对A对象集合进行筛选。

这样处理感觉不够方便,数据维护人员需要记住A的id,这很容易填错id。不希望让维护人员了解这些ID,所以就希望能够在A对象的列表界面加一个“添加B对象”字段,当点击这个字段的时候,即可调出B对象的添加界面,django admin支持这种自定义字段,在A对象中如下设置即可:

    def new-B(self):
        return u’<a href="/admin/xxapp/B/add/?a=%d">新建 B</a>’  %  self.id
    new-B.allow_tags = True

通过这种自定义的方式可以添加很多操作,链接会带到任何想执行的功能。

B对象的添加界面出来之后,不希望还要了解A对象的id,因为这是从一个A对象发起的添加操作。所以需要把A对象ID传到B的添加界面中。参数的传递只能通过GET进行了,考察了django.contrib.admin.options,他是支持GET参数的,于是就这样把A对象的ID细节给隐藏掉了。如果怕用户不小心修改了A对象的ID,则可以使用javascript将这个input编辑框给disable掉。

django admin支持添加css和javascript:如下例:

    class ArticleAdmin(admin.ModelAdmin):
        class Media:
            css = {
                "all": ("my_styles.css",)
            }
            js = ("my_code.js",)

B添加完成之后,还希望继续添加另外一个B,也是基于同样的A对象,点击“保存并增加另一个”,这时候GET信息丢失了,A对象ID没有了。第一反映是希望用javascript把“保存并增加另一个”的链接加上GET信息,查看了页面的源代码,是一个submit的操作,没有链接可以修改的。

input type="submit" value="保存并增加另一个" name="_addanother" /

还是到服务端来考察,在django.contrib.admin.options中查找_addanother,在response_add函数中针对_addanother进行了处理,于是事情就简单了,在B的ModelAdmin对象中重写response_add函数:

def response_add(self, request, obj, post_url_continue=’../%s/’):       
        if request.POST.has_key("_addanother"):
            from django.utils.translation import ugettext as _
            from django.utils.encoding import force_unicode
            from django.http import HttpResponseRedirect
            opts = obj._meta
            pk_value = obj._get_pk_val()           
            msg = _(’The %(name)s "%(obj)s" was added successfully.’) % {’name’: force_unicode(opts.verbose_name), ‘obj’: force_unicode(obj)}           
            self.message_user(request, msg + ‘ ‘ + (_("You may add another %s below.") % force_unicode(opts.verbose_name)))

            #新增加代码,记录下GET的信息
            getinfos = request.GET.items()
            gets = ‘?’
            for info in getinfos:
                gets += ‘%s=%s&’ % (info[0],info[1])
            path = request.path + gets

            return HttpResponseRedirect(path)
        return super(admin.ModelAdmin, self).response_add(request,obj,post_url_continue)

这样GET信息就可以保存下来了。

查看了django的最新版本,GET信息还是没有保存,这个不应该,提了一个ticket上去。

分类: django, python 标签:
  1. 本文目前尚无任何评论.
  1. 本文目前尚无任何 trackbacks 和 pingbacks.