django-使用jquery完成ajax,实例-选择省市区

使用Ajax

  • 使用视图通过上下文向模板中传递数据,需要先加载完成模板的静态页面,再执行模型代码,生成最张的html,返回给浏览器,这个过程将页面与数据集成到了一起,扩展性差
  • 改进方案:通过ajax的方式获取数据,通过dom操作将数据呈现到界面上
  • 推荐使用框架的ajax相关方法,不要使用XMLHttpRequest对象,因为操作麻烦且不容易查错
  • jquery框架中提供了$.ajax、$.get、$.post方法,用于进行异步交互
  • 由于csrf的约束,推荐使用$.get
  • 示例:实现省市区的选择
  • 最终实现效果如图:

引入js文件

  • js文件属于静态文件,创建目录结构如图:

 修改settings.py关于静态文件的设置

STATIC_URL = '/static/'
STATICFILES_DIRS = [
    os.path.join(BASE_DIR, 'static'),
]

在models.py中定义模型

class AreaInfo(models.Model):
title=models.CharField(max_length=20)
parea=models.ForeignKey('self',on_delete=models.CASCADE,null=True,blank=True)

settings.py文件INSTALLED_APPS添加app

INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'booktest',
]

修改settings.py关于DATABASES的设置

DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': 'ttsx1',
'USER':'root',
'PASSWORD':'mysql123',
'HOST':'localhost',
'PORT':3306
}
}

生成迁移

python manage.py makemigrations
python manage.py migrate

通过Navicat向表中填充示例数据

  • 参见“省市区.sql”
  • 注意将表的名称完成替换

在views.py中编写视图

  • index用于展示页面
  • pro用于返回省级数据
  • city用于根据省、市编号返回市、区信息,格式都为字典对象
 1 from django.shortcuts import render
 2 from .models import *
 3 from django.http import HttpResponse,JsonResponse
 4 
 5 # Create your views here.
 6 
 7 def index(request):
 8     return render(request,'booktest/index.html')
 9 
10 #省的信息
11 def pro(request):
12     data=AreaInfo.objects.filter(parea__isnull=True)
13     list=[]
14     #[[1,北京],[2,河北],...]
15     for pro in data:
16         list.append([pro.id,pro.title])
17     return JsonResponse({'data':list})
18 
19 #市和区的信息
20 def city(request,id):
21     data=AreaInfo.objects.filter(parea_id=id)
22     list=[]
23     #[{id:1,title:北京},{id:2,title:河北},...]
24     for city in data:
25         list.append({'id':city.id,'title':city.title})
26     return JsonResponse({'data':list})

在urls.py中配置urlconf

1 from django.conf.urls import url,include
2 from . import views
3 
4 urlpatterns = [
5     url(r'^index/$',views.index),
6     url(r'^pro/$',views.pro),
7     url(r'^city(\d+)/$',views.city),
8 ]

主urls.py中包含此应用的url

1 from django.contrib import admin
2 from django.urls import path
3 from django.conf.urls import url,include
4 
5 urlpatterns = [
6     path('admin/', admin.site.urls),
7     url(r'^',include('booktest.urls'))
8 ]

定义模板index.html

  • 在项目中的目录结构如图:

  • 修改settings.py的TEMPLATES项,设置DIRS值
'DIRS': [os.path.join(BASE_DIR,'templates')],
  • 定义模板文件:

  • 包含三个select标签,分别存放省市区的信息

  • 在模板中引入jquery文件

  • 编写js代码

    • 绑定change事件
    • 发出异步请求
    • 使用dom添加元素
 1 <!DOCTYPE html>
 2 <html lang="en">
 3 <head>
 4     <meta charset="UTF-8">
 5     <title>index</title>
 6     <script src="/static/booktest/jquery-1.12.4.min.js"></script>
 7     <script>
 8         $(function(){
 9             //使用ajax加载省信息
10             pro=$('#pro')
11             $.get('/pro/',function(dic){       //dic格式为{data:[[],[],[],]}
12                 $.each(dic.data,function(index,item){      //item格式为[id,title]
13                     pro.append('<option value="'+item[0]+'">'+item[1]+'</option>')     //节点操作,添加元素
14                 })
15             });
16 
17             //获取市的信息
18             $('#pro').change(function(){
19                 //alert($(this).val())    //弹出省对应的value值
20                 $.get('/city'+$(this).val()+'/',function(dic){   //dic格式为{data:[{},{}...]}
21                     city=$('#city')
22                     city.empty().append('<option value="">请选择市</option>')     //empty()把所有段落的子元素(包括文本节点)删除
23                     $('#dis').empty().append('<option value="">请选择区</option>')
24                     $.each(dic.data,function(index,item){
25                         city.append('<option value="'+item.id+'">'+item.title+'</option>')
26                     })
27                 })
28             });
29 
30             //获取区的信息
31             $('#city').change(function(){
32                 $.get('/city'+$(this).val()+'/',function(dic){
33                     dis=$('#dis')
34                     dis.empty().append('<option value="">请选择区</option>')
35                     $.each(dic.data,function(index,item){
36                         dis.append('<option value="'+item.id+'">'+item.title+'</option>')
37                     })
38                 })
39             })
40         })
41     </script>
42 
43 </head>
44 <body>
45     <select id="pro">
46         <option value="">请选择省</option>
47     </select>
48     <select id="city">
49         <option value="">请选择市</option>
50     </select>
51     <select id="dis">
52         <option value="">请选择区</option>
53     </select>
54 </body>
55 </html>

 

补充:

自连接

  • 对于地区信息,属于一对多关系,使用一张表,存储所有的信息
  • 类似的表结构还应用于分类信息,可以实现无限级分类
  • 新建模型AreaInfo,生成迁移
class AreaInfo(models.Model):
    atitle = models.CharField(max_length=20)
    aParent = models.ForeignKey('self', null=True, blank=True)
  • 访问关联对象
上级对象:area.aParent
下级对象:area.areainfo_set.all()
  • 加入测试数据(在workbench中,参见“省市区mysql.txt”)
  • 在booktest/views.py中定义视图area
from models import AreaInfo
def area(request):
    area = AreaInfo.objects.get(pk=130100)
    return render(request, 'booktest/area.html', {'area': area})
  • 定义模板area.html
<!DOCTYPE html>
<html>
<head>
    <title>地区</title>
</head>
<body>
当前地区:{{area.atitle}}
<hr/>
上级地区:{{area.aParent.atitle}}
<hr/>
下级地区:
<ul>
    { %for a in area.areainfo_set.all%}
    <li>{{a.atitle}}</li>
    { %endfor%}
</ul>
</body>
</html>
  • 在booktest/urls.py中配置一个新的urlconf
urlpatterns = [
    url(r'^area/$', views.area, name='area')
]

posted on 2020-02-02 11:01  cherry_ning  阅读(326)  评论(0)    收藏  举报

导航