django框架的中间件

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/hard_days/article/details/88384539

高级

到此为止,关于Django框架的三大块M、V、T已经全部讲完了,接下来学习一些其它的知识点,这些知识点不在三大块范围内,Django提供了这些功能后,可以帮助我们更快更好的完成开发。

主要知识点如下:

  • 静态文件处理

  • 中间件

  • 上传图片

  • Admin站点

  • 分页

  • 示例:省市区选择,jquery,ajax

1、创建示例项目

1)创建项目demo5。

django-admin startproject demo5

2)进入项目目录demo5,创建应用app1。

cd test5
python manage.py startapp app1

3)在demo5/settings.py中INSTALLED_APPS项安装应用。

4)在demo5/settings.py中DATABASES项配置使用MySQL数据库demo5。

5)在demo5/settings.py中TEMPLATES项配置模板查找路径。

6)创建模板目录结构如下:

7)打开demo5/urls.py文件,包含app1的url配置。

8)在app1/目录下创建urls.py,配置url。

from django.conf.urls import url
from app1 import views
urlpatterns=[
    url(r'^$',views.index),
]

10)打开app1/views.py文件,定义视图index。

from django.shortcuts import render
​
def index(request):
    return render(request,'app1/index.html')

11)在templates/app1目录下创建文件index.html,代码如下:

<html>
<head>
    <title>常用技术练习</title>
</head>
<body>
<h1>今天学习常用的技术</h1>
</body>
</html>

12)打开app1/models.py文件,定义模型类AeraInfo,结构参照第二部分设计。

from django.db import models
​
#定义地区模型类,存储省、市、区县信息
class AreaInfo(models.Model):
    atitle=models.CharField(max_length=30)#名称
    aParent=models.ForeignKey('self',null=True,blank=True)#父级

1、静态文件

项目中的CSS、图片、js都是静态文件。一般会将静态文件放到一个单独的目录中,以方便管理。在html页面中调用时,也需要指定静态文件的路径,Django中提供了一种解析的方式配置静态文件路径。静态文件可以放在项目根目录下,也可以放在应用的目录下,由于有些静态文件在项目中是通用的,所以推荐放在项目的根目录下,方便管理。

示例

1)在demo5/settings.py文件中定义静态文件存放的物理目录。

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

2)在项目根目录下创建static目录,再创建img、css、js目录。

3)在app1/views.py中定义视图static_test。

def static_test(request):
    return render(request,'app1/static_test.html')

4)在app1/urls.py中配置url。

    url(r'^static_test/$',views.static_test),

5)在templates/app1/下创建static_test.html文件。

<html>
<head>
    <title>静态文件</title>
</head>
<body>
<img src="/static/img/sta.png"/>
</body>
</html>

6)保存图片到static/img/目录下,名称为sta.png。

7)运行服务器,浏览效果如下图:

配置静态文件

Django提供了一种配置,可以在html页面中可以隐藏真实路径。

1)在demo5/settings.py文件中修改STATIC_URL项。

# STATIC_URL = '/static/'
STATIC_URL = '/abc/'

2)刷新浏览器,图片找不到了,效果如下图:

3)修改templates/app1/static_test.html如下:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>静态文件</title>
</head>
<body>
<h1>下面没有修改的图片</h1>
<img src="static/img/sta.jpg" alt="">
<hr>
<h1>下面是修改路径后的图片</h1>
<img src="aaa/img/sta.jpg" alt="">
</body>
</html>

3)刷新浏览器,效果如下图:

4)查看网页源代码,发现可以网址和真实地址之间没有关系。

为了安全可以通过配置项隐藏真实图片路径,在模板中写成固定路径,后期维护太麻烦,可以使用static标签,根据配置项生成静态文件路径。

1)修改templates/app1/static_test.html如下:

<html>
<head>
    <title>静态文件</title>
</head>
<body>
修改前:<img src="/static/img/sg.png"/>
<hr>
修改后:<img src="/abc/img/sg.png"/>
<hr>
动态配置:
{%load static from staticfiles%}
<img src="{%static "img/sg.png" %}"/>
</body>
</html>

2)刷新浏览器

查看网页源代码如下图:

说明:这种方案可以隐藏真实的静态文件路径,但是结合Nginx布署时,会将所有的静态文件都交给Nginx处理,而不用转到Django部分,所以这项配置就无效了。

2、中间件

Django中的中间件是一个轻量级、底层的插件系统,可以介入Django的请求和响应处理过程,修改Django的输入或输出。中间件的设计为开发者提供了一种无侵入式的开发方式,增强了Django框架的健壮性,其它的MVC框架也有这个功能,名称为IoC。

Django在中间件中预置了五个方法,这五个方法的区别在于不同的阶段执行,对输入或输出进行干预,方法如下:

1)初始化:无需任何参数,服务器响应第一个请求的时候调用一次,用于确定是否启用当前中间件。

def __init__(self):
    pass

2)处理请求前:在每个请求上,request对象产生之后,url匹配之前调用,返回None或HttpResponse对象。

def process_request(self, request):
    pass

3)处理视图前:在每个请求上,url匹配之后,视图函数调用之前调用,返回None或HttpResponse对象。

def process_view(self, request, view_func, *view_args, **view_kwargs):
    pass

4)处理响应后:视图函数调用之后,所有响应返回浏览器之前被调用,在每个请求上调用,返回HttpResponse对象。

def process_response(self, request, response):
    pass

5)异常处理:当视图抛出异常时调用,在每个请求上调用,返回一个HttpResponse对象。

def process_exception(self, request,exception):
    pass

示例

中间件是一个独立的python类,,可以定义这五个方法中的一个或多个。

1)在app1/目录下创建middleware.py文件,代码如下:

class MyMedd:
​
    def __init__(self):
        print ('------init--------')
​
    def process_request(self,request):
        print ('------request--------')
​
    def process_view(self,request, view_func, *view_args, **view_kwargs):
        print ('--------view------')
​
    def process_response(self,request, response):
        print('-------response---')
        return response

2)在demo5/settings.py文件中,向MIDDLEWARE_CLASSES项中注册。

3)修改app1/views.py中视图index。

def index(request):
    print('-------index--------')
    return render(request,'app1/index.html')

4)运行服务器,命令行中效果如下图:

异常中间件

1)在app1/middleware.py中定义两个异常类如下:

class Exp1:
    #异常中间键
    def process_exception(self,request,exception):
        return HttpResponse('出错啦')

2)在demo5/settings.py文件中,向MIDDLEWARE_CLASSES项中注册。

3)修改app1/views.py中视图index。

def index(request):
    print(abc)  #abc没有定义,此行代码将引发异常
    return render(request,'app1/index.html')

4、访问index页面,结果如下

注意:如果多个注册的中间件类中都有process_exception的方法,则先注册的后执行。

3、Admin站点

内容发布的部分由网站的管理员负责查看、添加、修改、删除数据,开发这些重复的功能是一件单调乏味、缺乏创造力的工作,为此,Django能够根据定义的模型类自动地生成管理模块。

在第一部分对管理站点做了简单介绍,现在做详细讲解。在Django项目中默认启用Admin管理站点。

1)准备工作:创建管理员的用户名和密码。

python manage.py createsuperuser

按提示填写用户名、邮箱、密码。

2)使用:在应用的admin.py中注册模型类

例:打开app1/admin.py文件,注册地区模型。

from django.contrib import admin
from app1.models import *
​
admin.site.register(AreaInfo)

3)输入如下网址:

http://127.0.0.1:8000/admin/

按提示填写用户名、密码,点击“Log in”按钮登录。

登录成功后,可以看到AreaInfos,可以进行增加、修改、删除、查询的管理。

3.1、控制管理页展示

类ModelAdmin可以控制模型在Admin界面中的展示方式,主要包括在列表页的展示方式、添加修改页的展示方式。

1)在app1/admin.py中,注册模型类前定义管理类AreaAdmin。

class AreaAdmin(admin.ModelAdmin):
    pass

管理类有两种使用方式:

  • 注册参数

  • 装饰器

注册参数:打开app1/admin.py文件,注册模型类代码如下:

admin.site.register(AreaInfo,AreaAdmin)

装饰器:打开app1/admin.py文件,在管理类上注册模型类,代码如下:

@admin.register(AreaInfo)
class AreaAdmin(admin.ModelAdmin):
    pass

接下来介绍如何控制列表页、增加修改页展示效果。

3.2、列表页选项

页大小

每页中显示多少条数据,默认为每页显示100条数据,属性如下:

list_per_page=100

1)打开app1/admin.py文件,修改AreaAdmin类如下:

class AreaAdmin(admin.ModelAdmin):
    list_per_page = 10

2)在浏览器中查看区域信息的列表页面,效果如下图:

3.21、"操作选项"的位置

顶部显示的属性,设置为True在顶部显示,设置为False不在顶部显示,默认为True。

actions_on_top=True

底部显示的属性,设置为True在底部显示,设置为False不在底部显示,默认为False。

actions_on_bottom=False

1)打开app1/admin.py文件,修改AreaAdmin类如下:

class AreaAdmin(admin.ModelAdmin):
    ...
    actions_on_top = True
    actions_on_bottom = True

2)在浏览器中刷新效果如下图:

3.2.2、列表中的列

属性如下:

list_display=[模型字段1,模型字段2,...]

1)打开app1/admin.py文件,修改AreaAdmin类如下:

class AreaAdmin(admin.ModelAdmin):
    ...
    list_display = ['id','atitle']

2)在浏览器中刷新效果如下图:

点击列头可以进行升序或降序排列。

3.2.3、将方法作为列

列可以是模型字段,还可以是模型方法,要求方法有返回值。

1)打开app1/models.py文件,修改AreaInfo类如下:

class AreaInfo(models.Model):
    ...
    def title(self):
        return self.atitle

2)打开app1/admin.py文件,修改AreaAdmin类如下:

class AreaAdmin(admin.ModelAdmin):
    ...
    list_display = ['id','atitle','title']

3)在浏览器中刷新效果如下图:

方法列是不能排序的,如果需要排序需要为方法指定排序依据。

admin_order_field=模型类字段

1)打开app1/models.py文件,修改AreaInfo类如下:

class AreaInfo(models.Model):
    ...
    def title(self):
        return self.atitle
    title.admin_order_field='atitle'

2)在浏览器中刷新效果如下图:

列标题

列标题默认为属性或方法的名称,可以通过属性设置。需要先将模型字段封装成方法,再对方法使用这个属性,模型字段不能直接使用这个属性。

short_description='列标题'

1)打开app1/models.py文件,修改AreaInfo类如下:

class AreaInfo(models.Model):
    ...
    title.short_description='区域名称'

2)在浏览器中刷新效果如下图:

关联对象

无法直接访问关联对象的属性或方法,可以在模型类中封装方法,访问关联对象的成员。

1)打开app1/models.py文件,修改AreaInfo类如下:

class AreaInfo(models.Model):
    ...
    def parent(self):
        if self.aParent is None:
          return ''
        return self.aParent.atitle
    parent.short_description='父级区域名称'

2)打开app1/admin.py文件,修改AreaAdmin类如下:

class AreaAdmin(admin.ModelAdmin):
    ...
    list_display = ['id','atitle','title','parent']

3)在浏览器中刷新效果如下图:

3.2.4、右侧栏过滤器

属性如下,只能接收字段,会将对应字段的值列出来,用于快速过滤。一般用于有重复值的字段。

list_filter=[]

1)打开app1/admin.py文件,修改AreaAdmin类如下:

class AreaAdmin(admin.ModelAdmin):
    ...
    list_filter=['atitle']

2)在浏览器中刷新效果如下图:

3.2.5、搜索框

属性如下,用于对指定字段的值进行搜索,支持模糊查询。列表类型,表示在这些字段上进行搜索。

search_fields=[]

1)打开app1/admin.py文件,修改AreaAdmin类如下:

class AreaAdmin(admin.ModelAdmin):
    ...
    search_fields=['atitle']

2)在浏览器中刷新效果如下图:

3.2.6、中文标题

1)打开app1/models.py文件,修改模型类,为属性指定verbose_name参数,

class AreaInfo(models.Model):
    atitle=models.CharField(verbose_name='标题',max_length=30)#名称
    ...

2)在浏览器中刷新效果如下图:

3.3、编辑页选项

3.3.1、显示字段顺序

属性如下:

fields=[]

1)点击某行ID的链接,可以转到修改页面,默认效果如下图:

2)打开app1/admin.py文件,修改AreaAdmin类如下:

class AreaAdmin(admin.ModelAdmin):
    ...
    fields=['aParent','atitle']

3)刷新浏览器效果如下图:

在下拉列表中输出的是对象的名称,可以在模型类中定义str方法用于对象转换字符串。

1)打开app1/models.py文件,修改AreaInfo类,添加str方法。

class AreaInfo(models.Model):
    ...
    def __str__(self):
        return self.atitle

2)刷新浏览器效果如下图:

3.3.2、分组显示

属性如下:

fieldset=(
    ('组1标题',{'fields':('字段1','字段2')}),
    ('组2标题',{'fields':('字段3','字段4')}),
)

1)打开app1/admin.py文件,修改AreaAdmin类如下:

class AreaAdmin(admin.ModelAdmin):
    ...
    # fields=['aParent','atitle']
    fieldsets = (
        ('基本', {'fields': ['atitle']}),
        ('高级', {'fields': ['aParent']})
    )

2)刷新浏览器效果如下图:

说明:fields与fieldsets两者选一使用。

3.3.3关联对象

在一对多的关系中,可以在一端的编辑页面中编辑多端的对象,嵌入多端对象的方式包括表格、块两种。 类型InlineModelAdmin:表示在模型的编辑页面嵌入关联模型的编辑。子类TabularInline:以表格的形式嵌入。子类StackedInline:以块的形式嵌入。

1)打开app1/admin.py文件,创建AreaStackedInline类。

class AreaStackedInline(admin.StackedInline):
    model = AreaInfo#关联子对象
    extra = 2#额外编辑2个子对象

2)打开app1/admin.py文件,修改AreaAdmin类如下:

class AreaAdmin(admin.ModelAdmin):
    ...
    inlines = [AreaStackedInline]

3)刷新浏览器效果如下图:

可以用表格的形式嵌入。

1)打开app1/admin.py文件,创建AreaTabularInline类。

class AreaTabularInline(admin.TabularInline):
    model = AreaInfo#关联子对象
    extra = 2#额外编辑2个子对象

2)打开app1/admin.py文件,修改AreaAdmin类如下:

class AreaAdmin(admin.ModelAdmin):
    ...
    inlines = [AreaTabularInline]

3)刷新浏览器效果如下图:

3.4、重写模板

1)在templates/目录下创建admin目录,结构如下图:

2)打开当前虚拟环境中Django的目录,再向下找到admin的模板,目录如下:

/home/python/.virtualenvs/py_django/lib/python3.5/site-packages/django/contrib/admin/templates/admin

3)将需要更改文件拷贝到第一步建好的目录里,此处以base_site.html为例。

编辑base_site.html文件:

{% extends "admin/base.html" %}
​
{% block title %}{{ title }} | {{ site_title|default:_('Django site admin') }}{% endblock %}
​
{% block branding %}
<h1 id="site-name"><a href="{% url 'admin:index' %}">{{ site_header|default:_('Django administration') }}</a></h1>
<hr>
<h1>自定义的管理页模板</h1>
<hr>
{% endblock %}
​
{% block nav-global %}{% endblock %}

4)在浏览器中转到列表页面,刷新后如下图:

其它后台的模板可以按照相同的方式进行修改。

4、上传图片

在python中进行图片操作,需要安装包PIL。

pip install Pillow==3.4.1

在Django中上传图片包括两种方式:

  • 在管理页面admin中上传图片

  • 自定义form表单中上传图片

上传图片后,将图片存储在服务器上,然后将图片的路径存储在表中。

4.1、创建包含图片的模型类

将模型类的属性定义成models.ImageField类型。

1)打开app1/models.py文件,定义模型类PicTest。

class PicInfo(models.Model):
    #存储图片路径的模型类
    #upload_to指定图片上传的存储路径
    pic_addr=models.ImageField(upload_to='app1/',verbose_name='图片路径')

2)回到命令行中,生成迁移。

python manage.py makemigrations

3)回到命令行中,执行迁移。

python manage.py migrate

4打开settings.py文件,设置图片保存路径。

因为图片也属于静态文件,所以保存到static目录下。

MEDIA_ROOT=os.path.join(BASE_DIR,"static/media")

5)在static目录下创建media目录,再创建应用名称的目录,此例为app1。

注:模型类中指定的上传路径app1就是就是这个app1目录

4.2、在管理页面admin中上传图片

1)打开app1/admin.py文件,注册PicTest。

from django.contrib import admin
from app1.models import *
​
admin.site.register(PicInfo)

2)运行服务器,输入如下网址。

http://127.0.0.1:8000/admin/

3)点击增加,打开新页面。

4)选择图片,点击“save”按钮完成图片上传。

5)回到数据库命令行,查询表app1_picinfo中的数据如下图(下图依次上传了三张图片):

6)数据库中只存储了图片路径,图片被保存到目录static/media/app1/下

4.3、自定义form表单中上传图片

1)打开app1/views.py文件,创建视图pic。

def pic(request):
    #上图片的视图
    return  render(request,'app1/pic.html')

2)打开app1/urls.py文件,配置url。

 url(r'^pic$',pic),

3)在templates/app1/目录下创建模板pic.html。

在模板中定义上传表单,要求如下:

  • form的属性enctype="multipart/form-data"

  • form的method为post

  • input的类型为file

<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>文件</title>
</head>
<body>
<h1>图片文件上传</h1>
<form action="/pic_handel" method="post" enctype="multipart/form-data" >
    {%csrf_token%}
    <input type="file" name="pic">
    <input type="submit" value="上传">   
</form>
</body>
</html>

4)打开app1/views.py文件,创建视图pic_handle,用于接收表单保存图片。request对象的FILES属性用于接收请求的文件,包括图片。

from demo5.settings import *  #把项目配置的settings模块导入过来,下面要用到部分配置的路径
from django.http import HttpResponse
...
def pic_handel(request):
    #处理上传的文件,并保存到上传的路径下面
    #获取文件
    pic = request.FILES.get('pic')
    #创建文件
    file_path_name=os.path.join(MEDIA_ROOT,file_name)
     #把上传文件的数据,写入到增加创建的文件中
    with(open(file_path_name,'wb')) as f1:
        #读取上传文件的数据
        for content in pic.chunks():  #获取上传文件中的数据
            f1.write(content)       #写入到文件中
    return HttpResponse('上传成功了')

5)打开app1/urls.py文件,配置url,。

url(r'^pic_handel$',pic_handel), #处理上传的图片    

6)运行服务器,在浏览器中输入如下网址:

选择文件后点击按钮上传图片。

7)图片上传目录如下图:

这里只是完成图片上传的代码,如果需要保存数据到表中需要创建Picinfo对象完成保存。

4.4、显示图片

1)打开app1/views.py文件,创建视图pic_show。

from app1.models import PicTest
...
def pic_show(request):
    pic=PicTest.objects.get(pk=1)
    context={'pic':pic}
    return render(request,'app1/pic_show.html',context)

2)打开app1/urls.py文件,配置url。

    url(r'^pic_show/$', views.pic_show),

3)在templates/app1/目录下创建模板pic_show.html。

<html>
<head>
    <title>显示上传的图片</title>
</head>
<body>
<img src="/static/media/{{pic.pic}}"/>
</body>
</html>

4)运行服务器,在浏览器中输入如下网址:

http://127.0.0.1:8000/pic_show/

5、分页

Django提供了数据分页的类,这些类被定义在django/core/paginator.py中。 类Paginator用于对列进行一页n条数据的分页运算。类Page用于表示第m页的数据。

5.1、Paginator类实例对象

  • 方法*init*(列表,int):返回分页对象,第一个参数为列表数据,第二个参数为每页数据的条数。

  • 属性count:返回对象总数。

  • 属性num_pages:返回页面总数。

  • 属性page_range:返回页码列表,从1开始,例如[1, 2, 3, 4]。

  • 方法page(m):返回Page类实例对象,表示第m页的数据,下标以1开始。

5.2、Page类实例对象

  • 调用Paginator对象的page()方法返回Page对象,不需要手动构造。

  • 属性object_list:返回当前页对象的列表。

  • 属性number:返回当前是第几页,从1开始。

  • 属性paginator:当前页对应的Paginator对象。

  • 方法has_next():如果有下一页返回True。

  • 方法has_previous():如果有上一页返回True。

  • 方法len():返回当前页面对象的个数。

  • page.next_page_number,下一页页码。

  • page.previous_page_number,上一页页码。

示例

1)在app1/views.py文件中创建视图page_test。

from django.core.paginator import *
​
def pro_all(request,index):
    print(index)
    #查询所有省份列表
    pro_list=AreaInfo.objects.filter(aParent__isnull=True)
    #进行分页,每页10条
    page = Paginator(pro_list,10)
    #获取页面列表
    page_list=page.page_range
    if index=='':  #判断index是否为空
        index=1
    else:
        if int(index) not in page_list:  #判断是否再页码的范围内
            index=1
    areas = page.page(index)  #获取第index页面内容
    #返回第index也页面内容和,页面列表信息
    return render(request,'app1/pro_all.html',{'areas':areas,'pages':page_list})
​

2)在app1/urls.py文件中配置url。

  url(r'^pro_all(\d*)$',pro_all),

3)在templates/app1/目录下创建page_test.html模板文件。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<h1>所有省份:</h1>
<!--显示当前页所有的地区名-->
<ul>
    {%for area in areas%}
    <li>{{area.atitle}}</li>
    {%endfor%}
​
</ul>
<!--判断事多有上一页-->
{% if areas.has_previous%}
<a href="pro_all{{areas.previous_page_number}}">上一页</a>
{%endif%}
​
<!--显示所有的页码列表-->
{% for page in pages %}
    <!--判断页码 是否为当前页,是当前页得话则不用加链接-->
    {% if areas.number == page %}
        {{page}}
    {%else%}
        <a href="/pro_all{{page}}">{{page}}</a>
    {% endif %}
{% endfor %}
<!--判断是否有下一页-->
<!--参考判断上一页-->
</body>
</html>

4)运行服务器,在浏览器中输入如下网址:

6、案列:通过下拉框选择并添加地址

本示例讲解在Django中使用jquery的ajax进行数据交互。 jquery框架中提供了.ajax、get、.post方法,用于进行异步交互,由于Django中默认使用CSRF约束,推荐使用get。

示例:实现省市区的选择。

最终实现效果如图:

1)将jquery文件拷贝到static/js/目录下。

2)打开app1/views.py文件,定义视图addr_select,用于显示下拉列表。

#1.定义视图。配置url,创建模板
def addr_select(request):
    return render(request,'app1/addr.html')#提供显示下拉列表的控件,供用户操作
​

3)打开app1/urls.py文件,配置url。

 url(r'^addr$',addr_select)

4)在templates/app1/目录下创建addr.html。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    {% load static from staticfiles%}
    <script type="text/javascript" src="{%static 'js/jquery-1.12.4.min.js'%}"></script>
    <script>
​
        $(function () {
            //发起ajax请求获取省份信息
             pro=$('#pro');
             city=$('#city');
             dis = $('#dis');
            $.get('/prov',function (data) {
                res=data.data;
                $.each(res,function (index,item) {
                    id = item[1];
                    title = item[0];
                    pro.append('<option value='+id+'>'+title+'</option>')
                })
            });
            pro.change(function () {
                pro_id = pro.val();
                $.ajax({
                    url:'/city',
                    data:{'id':pro_id},
                    type:'get'
                }).success(function (data) {
                    res1=data.data;
                        //遍历数据
                    dis.empty().append('<option value="">选择县</option>');
                    city.empty().append('<option value="">选择市</option>');
                    for(i=0;i<res1.length;i++){
                        id=res1[i][1];
                        title=res1[i][0];
                        city.append('<option value='+id+'>'+title+'</option>')
                    }
                    })
            });
            city.change(function () {
                city_id = city.val();
               $.get('/city?'+'id='+city_id,function (data) {
                   res2 = data.data;
                   dis.empty().append('<option value="">请选择县</option>');
                   $.each(res2,function (index,item) {
                       id=item[1];
                       title=item[0];
                       dis.append('<option value='+id+'>'+title+'</option>')
                   })
               })
            });
​
            //获取整条信息,并显示出来
            btn=$('#btn');
            addr=$('#addr');
            addr_ul=$('#addr_ul');
            btn.click(function () {
                pro_info = $('#pro option:selected').text();
                city_info = $('#city option:selected').text();
                dis_info = $('#pro option:selected').text();
                addr_info = addr.val();
                addr_str=pro_info+city_info+dis_info+addr_info;  //拼接完整的地址
                addr_ul.append('<li>'+addr_str+'</li>');
            })
        })
    </script>
</head>
<body>
<url id="addr_ul">
</url>
请选择:
<select name="" id="pro">
    <option value="">请选择省</option>
</select>
<select name="" id="city">
    <option value="">请选择市</option>
</select>
<select name="" id="dis">
    <option value="">请选择县</option>
</select>
<br>
详细地址:<input type="text" id="addr">
<input id="btn" type="submit" value="添加">
</body>
</html>

5)运行服务器,在浏览器中输入如下网址:

http://127.0.0.1:8000/addr

6)打开app1/views.py文件,定义视图addr_pro,用于获取省信息。

from django.http import JsonResponse
...
#2.获取所有省份的信息,返回到页面上
def addr_pro(request):
    pro_list = AreaInfo.objects.filter(aParent__isnull=True)
    areas=[(area.id,area.atitle)for area in pro_list]
    #返回所有的省份ID和名称
    return JsonResponse({"areas":areas})

7)打开app1/urls.py文件,配置url。

  url(r'^addr_prov$',addr_pro)

8)打开app1/views.py文件,定义视图addr_city,用于根据编号获取对应的子级信息,如果传递的是省编号则获取市信息,如果传递的是市编号则获取区县信息。

#3.根据选择的上级地区,查询对应的下级地区的信息,返回到页面上
def addr_city(request):
    pid=request.GET.get('id')  #获取请求中的地区id
    print(pid)
    area = AreaInfo.objects.get(id=pid)
    print(area.atitle)
    #一到多的关联查询,类对象
    areas_list = area.areainfo_set.all()
    areas = [(area.id,area.atitle) for area in areas_list]
​
    return JsonResponse({'areas':areas}
​

9)打开app1/urls.py文件,配置url。

 url(r'^addr_city$',addr_city)

10)在浏览器中输入如下网址:

http://127.0.0.1:8000/addr

猜你喜欢

转载自blog.csdn.net/hard_days/article/details/88384539