环境:
Python 3.6.4
Django 1.8.2
用上面的环境遭遇了以下两项错误:
1.AttributeError: module 'html.parser' has no attribute 'HTMLParseError'
这是因为HTMLParseError在pythons3.5已经没有了,需要将python版本回退到3.3或3.4。
2.str' object has no attribute 'resolve
这是因为django1.8以上的版本,在配置urls.py文件时,使用的是正则表达式替换原来的patterns。
原来的是这样的
1 | urlpatterns = patterns( '' , |
2 | (r '^$' , direct_to_template, { 'template' : 'a.html' }), |
1.8以后的变成这样的了。
2 | (r '^$' , direct_to_template, { 'template' : 'a.html' }), |
3.django 1.7使用的是def __str__(self),如果是使用def __unicode__(self)的,还要退回以前更低的版本。
所以将环境退回:
Python 3.4
django 1.7.2
一、虚拟环境
在Anaconda的base环境下,执行conda create -n xx命令建立的虚拟环境。然后使用命令激活它。使用pip命令安装Django。
conda create -n select python=3.4
conda activate select
pip install -i https://pypi.douban.com/simple/ Django==1.7.2
二、创建项目及应用
django-admin startproject ajaxselect
cd ajaxselect
python manage.py startapp djmenu
并将djmenu添加到setting.py的INSTALLED_APPS里面。
三、数据库
修改djmenu/models.py,加入models。
1 | class Province(models.Model): |
2 | name = models.CharField(max_length=30) |
8 | class City(models.Model): |
9 | name = models.CharField(max_length=40) |
10 | province = models.ForeignKey(Province) |
16 | class SelectP(models.Model): |
17 | province = models.ForeignKey(Province) |
18 | city = models.ForeignKey(City) |
并通过以下两条命令生成数据库。
python manage.py makemigrations polls
python manage.py migrate
四、forms.py
在models.py的同级目录,建立forms.py文件,内容如下:
1 | from django import forms |
2 | from .models import SelectP |
4 | class SelectForm(forms.ModelForm): |
五、后台
admin.py文件
1 | from .models import Province,City |
3 | # Register your models here. |
4 | admin.site.register(Province) |
5 | admin.site.register(City) |
再使用python manage.py createsuperuser设定后台的账号,密码,再运行python manage.py runserver
六、视图
views.py文件
1 | from django.shortcuts import render_to_response, get_object_or_404, redirect, urlresolvers, RequestContext |
2 | from django.core import serializers |
3 | from django.http import HttpResponse |
4 | from .models import Province, SelectP |
5 | from .forms import SelectForm |
6 | # Create your views here. |
10 | if request.method == 'POST' : |
11 | form = SelectForm(request.POST) |
14 | return redirect(urlresolvers.reverse( 'select_index' )) |
16 | return HttpResponse( 'error' ) |
18 | pro = Province.objects.all() |
19 | se = SelectP.objects.all() |
20 | return render_to_response( 'djmenu/index.html' , { 'province' :pro, 'select' :se}, |
21 | context_instance=RequestContext(request)) |
25 | pk = request.GET[ 'pk' ] |
26 | province = get_object_or_404(Province, pk=pk) |
27 | citys = province.city_set.all() |
28 | data = serializers.serialize( 'json' , citys) |
29 | return HttpResponse(data, content_type= 'application/json' ) |
七、配置url
1 | urlpatterns = patterns( 'djmenu.views' , |
2 | url(r '^index/$' , 'index' , name= 'select_index' ), |
3 | url(r '^getdata/$' , 'getdata' , name= 'getdata' ), |
4 | url(r '^admin/' , include (admin.site.urls)) |
八、模板
创建djmenu/templates/djmenu/目录,在该目录下创建index.html。
5 | <title>{% block title %}{% endblock %}</title> |
12 | <form class = "form-horizontal" action= "{% url 'select_index' %}" method= "post" > |
14 | <div class = "form-group" > |
15 | <label for = "id_province" class = "control-label" >选择省市</label> |
16 | <select class = "form-control" id= "id_province" name= "province" > |
17 | <option selected= "selected" >请选择</option> |
18 | {% for foo in province %} |
19 | <option value= "{{ foo.id }}" >{{ foo.name }}</option> |
23 | <div class = "form-group" > |
24 | <label for = "id_city" class = "control-label" >选择城市</label> |
25 | <select class = "form-control" id= "id_city" name= "city" > |
26 | <option selected= "selected" >请选择</option> |
29 | <div class = "form-group" > |
30 | <input type= "submit" value= "提交" > |
33 | <table class = "table table-bordered" > |
41 | {% for foo in select %} |
43 | <td>{{ foo.province.name }}</td> |
44 | <td>{{ foo.city.name }}</td> |
51 | $( '#id_province' ).change( function (){ |
52 | var id = $( '#id_province' ).val(); |
53 | $.getJSON( "{% url 'getdata' %}?pk=" +id, function (data,textStatus){ |
55 | $.each(data, function (i, item){ |
56 | content+= '<option value=' +item.pk+ '>' +item.fields.name+ '</option>' |
58 | $( '#id_city' ).html(content) |
在这里,使用{% url 'select_index' %}这样的形式,其实select_index就是对应urls.py中的index/这个url的名称。
九、添加数据
进入后台,添加相关省份、城市的数据。

十、成果展示
上方选择省份、城市之后,点击“提交”按钮,就可以看到刚刚选择的城市出现在最下方。

进入数据库,可以看到保存的选择信息。

十一、修改样式
将其中的
1 | <form class = "form-horizontal" action= "{% url 'select_index' %}" method= "post" > |
改成:
1 | <form class = "form-inline" action= "{% url 'select_index' %}" method= "post" > |
则样式会变成这样:

后记:本来打算1小时弄完的东西,到最后完工花了差不多4小时,时间管理啊!
作者:蜗牛博客