Django Admin外键选择的自动完成

原创声明:本文除了标明引用的内容外,都为本人原创,请尊重本人的知识产权,不能用于商业用途。欢迎转载,转载请在文章开头处插入以下内容:

本文转载自"狂龙ing”的Blog,地址为“http://blog.csdn.net/kuanglong2016/article/details/17173939"

问题

Django Admin使用select来作为Model的外键数据输入,但是如果外键记录数目很大(比如>1000),我们就很难快速地选择指定的外键。最多能使用首字母来快速定位,但首字母相同的选项也很多,所以这种办法有效性有限,而且如果外键显示项为 中文时就完全无效了,因此我们需要一种可以帮我们快速定位指定外键的办法。

背景知识

Django是使用人数最多的Python Web开发框架,其中Django Admin模块更是其中的精华,它可以帮助开发人员快速地建立一个模型数据的“增删改查”系统。而且在最新的1.6版中,该模块已经默认开启。(推荐大家使用)

思路和方法

由于Django Admin中默认使用select,本人一度考虑不使用Django Admin,而是自己做一个数据的“增删改查”后台系统,但是实在不舍得Django Admin的便捷性,于是祭出神Google大法,经过search and search,发现大多数人都推荐 django-extensionsdjango-autocomplete-light这两个关于自动完成的包,于是决定使用拿来主义从中间挑一个。

我首先使用的是django-extensions(因为看到别人用起来好简单的)
1. 安装&测试:
>>>  pip install django-extensions
>>>  python -c "import django_extensions; print django_extensions.VERSION"
2. 加入Django项目: 
INSTALLED_APPS = (
    ...
    'django_extensions',
)
3. 在代码中使用django-extensions:在app/admin.py中添加django_extension
from django.contrib import admin
from django_extensions.admin import ForeignKeyAutocompleteAdmin
import models

# Register your models here.
class LessonAdmin(ForeignKeyAutocompleteAdmin):
    related_search_fields = {
        'xyClass': ('name',)
    }

admin.site.register(models.XYClass)
admin.site.register(models.Lesson, LessonAdmin)
4. 完成后测试可以正常访问/admin/,但是页面还是没有任何变化,select也没变,通过Firebug查看可以看到错误如下

从错误提示可以看出,是没有正确的引入jQuery库,但是在Firebug的“脚本”标签栏中,明明白白可以看到有jQuery库。
Google之:从 Django Admin文档Mark van Lent的博客中发现,原来因为Django Admin本身需要jQuery库,但是为了不污染全局命名空间,使用django.jQuery作为jQuery库的名字空间(注:JavaScript中实际上是没有名字空间这个说法的,但是我不知道该用其它什么词语)。因此$就要用django.jQuery来代替,但是在使用其它的一些jQuery Plugin时,就会发生 $ is undefined 错误,比如jQuery Autocomplete(如上图)。
Mark van Lent介绍了解决该问题的三种方法:
1. 再引入一份jQuery,这样就可以在全局命名空间中使用$;
2. 修改Plugin代码,用django.jQuery取代jQuery以及$;
3. 重新定义变量$或者jQuery。
因为其它方法2需要耗费很多时间,方法3不知道在哪里定义,所以我使用方法1。
在使用Django Admin时,如果需要添加其它JavaScript库,在Admin子类中添加Media类,如下:
from django.contrib import admin
from django_extensions.admin import ForeignKeyAutocompleteAdmin
import models

# Register your models here.
class LessonAdmin(ForeignKeyAutocompleteAdmin):
    related_search_fields = {
        'xyClass': ('name',)
    }
    class Media:
        js = ("//code.jquery.com/jquery-1.10.2.min.js",) #在这里添加自己的jQuery库

admin.site.register(models.XYClass)
admin.site.register(models.Lesson, LessonAdmin)
使用Firebug测试,$已经可以使用,但是还是出现下面错误:


又Google了好一通,但是能力有限,无法解决。遂决定放弃,改用django-autocomplete-light

首先根据django-autocomplete-light在github上的链接,找到了它的文档 http://django-autocomplete-light.readthedocs.org/en/v2/demo.html,并根据该文档指南一步一步往下操作,最后成功启动服务器 ./manage.py runserver 0.0.0.0:8001,文档中使用的是 ./manage.py runserver,但是因为这样的话就只能在本机上用浏览器访问,但是我是通过ssh在远程开发机上做的开发,所以需要使用地址和端口 0.0.0.0:8001,这样才能在其它机器上使用浏览器访问( 参考doc)。浏览器显示“ A server error occurred. Please contact the administrator.” 服务器上显示错误 AttributeError: 'module' object has no attribute 'GenericModelForm'   。因为指南说明有两个示例,test_project和test_remote_project,所以我想既然不是本地访问,可能应该使用test_remote_project才行。于是我打开两个console,一个在test_project目录中运行 ./manage.py runserver,另一个在test_remote_project目录中运行 ./manage.py runserver 0.0.0.0:8001。测试可以正常访问/admin/并使用test/test登录成功,但是在测试自动完成时,当我在添加Address的Form中的city项时,输入Hous时(我准备输入Houston的),弹出框里并没有我想要的城市名称提示,而是 ValueError
检查服务器发现:
test_project显示错误
test_remote_project显示错误

然后又是一顿Google,但是本人水平实在有限,最后还是没有搞定,真的是准备放弃了,弄了这么久,居然还是一点成效都没有。但是转念一想,既然大家都推荐它,它应该还是很好用的,干脆也不用这个指南中的示例来测试了,直接放到自己的项目中试试看。
于是参照了另一篇文档安装文档 http://django-autocomplete-light.readthedocs.org/en/latest/install.html,实施过程如下:


1. 安装:
>>>   pip install django-autocomplete-light
2. 加入Django项目:
INSTALLED_APPS = [
    ...
    'autocomplete_light',
]
3. 在urls.py里的 admin.autodiscover() 前添加 autocomplete_light.autodiscover() 添加代码后的样子一般如下
import autocomplete_light
# import every app/autocomplete_light_registry.py
autocomplete_light.autodiscover()

import admin
admin.autodiscover()
4. 添加autocomplete_light.urls:在使用自动完成的时候,admin会使用ajax的方式与autocomplete_light.urls通信
from django.conf.urls import patterns, url, include


urlpatterns = patterns('',
    ...
    url(r'^autocomplete/', include('autocomplete_light.urls')),
)
5. 修改admin/base_site.html,该文件一般都在/usr/local/lib/python[版本号]/dist-packages/django/contrib/admin/templates/admin里。先备份base_site.html,再用以下内容覆盖
{% extends "admin/base.html" %}

{% block extrahead %}
    <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.9.0/jquery.js" type="text/javascript"></script>
    {% include 'autocomplete_light/static.html' %}
{% endblock %}
6. 注册Autocomplete类:添加app/autocomplete_light_register.py,内容一般如下
import autocomplete_light
from models import Person

# This will generate a PersonAutocomplete class
autocomplete_light.register(Person,
    # Just like in ModelAdmin.search_fields
    search_fields=['^first_name', 'last_name'],
    # This will actually html attribute data-placeholder which will set
    # javascript attribute widget.autocomplete.placeholder.
    autocomplete_js_attributes={'placeholder': 'Other model name ?',},
)
7. 为admin提供具有自动完成功能的ModelForms
from django.contrib import admin
import autocomplete_light
from models import Order

class OrderAdmin(admin.ModelAdmin):
    # This will generate a ModelForm
    form = autocomplete_light.modelform_factory(Order)
admin.site.register(Order)
按照指南中的说法,到这里应该已经可以实现外键的自动完成功能了。于是我便满怀期待地使用Admin去添加Order记录,但是还是没有任何变化,打开Firebug也没有看到任何错误。郁闷...真的出了郁闷还是郁闷....郁闷...真的太郁闷了...6个小时居然啥也没干成,我都快要崩溃了。不过真是应了这句“山穷水复疑无路,柳暗花明又一村”,就在我快要放弃的时候,我突然发现我打开的一个页面里的内容与上面有一点点不一样 ,大喜!!!(为什么还没有使就会大喜呢,嘿嘿嘿,说来惭愧,因为之前看到admin.site.register(Order)时就觉得纳闷,为什么不是Admin常用的admin.site.register(Order, OrderAdmin)呢,但是也没有深究,后来不成功也没有往这方面想。现在居然看到了我原来想的那种用法,当然很开心,感觉很可能问题就是它了)
from django.contrib import admin
import autocomplete_light
from models import Order

class OrderAdmin(admin.ModelAdmin):
    # This will generate a ModelForm
    form = autocomplete_light.modelform_factory(Order)
#admin.site.register(Order) #error
admin.site.register(Order, OrderAdmin)
再次打开..:8000/admin页面,测试,成功!!!(截图如下)开心,狂喜!!!哈哈哈哈哈 大笑 大笑 大笑


总结

这种通过自动完成外键的方法可以大大提高数据输入的效率,而且django-autocomplete-light不仅仅只用于Django Admin,在自定义页面中也可以使用。
(这篇博文是我第一次用这样叙事的方式来写,写得很乱,但是因为中途实在是太郁闷了,不写不快,希望各位看客见谅)

主要参考文献

  • 5
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值