Django中辅助技术总结[静态文件,中间件,上传图片,分页案例]
静态文件的设置
静态文件概述:
在网页使用的css文件,js文件和图片叫做静态文件。
设置流程:
- 在项目目录中创建static文件夹
- 在创建的文件夹里分别创建js,css,img文件夹
- 在setting.py文件中做以下配置
STATICFILES_DIRS = [os.path.join(BASE_DIR, 'static')] # 设置静态文件的物理地址
- 设置静态文件路径
STATIC_URL = '/abc/' # 和物理目录是对应的关系, 逻辑上的概念
动态获取STATIC_URL的方法
- 在模板文件中加载路径
{% load staticfiles %}
- 在图片的地址写入
<img src="{% static 'img/mm.jpg' %}" alt="">
<img src="/abc/img/mm.jpg" alt="">
# 以上两种效果相同
- 最终在浏览器渲染成:
动态获取STATIC_URL的地址<br> <img src="/abc/img/mm.jpg" alt="">
总结:
- /abc/img/mm.jpg 隐藏了服务器端实际保存文件的目录
- 当STATIC_URL = '/abc/'这个路径设置为/abc/时加载图片时会到物理地址STATICFILES_DIRS设置项目录下去查找,查找时的路径从img文件夹开始
中间件
点击查看中间件详解: http://www.crazyant.net/1001.html
获取访问浏览器的ip地址:
request.META['REMOTE_ADDR']
作用:根据指定的Ip限制浏览器的用户访问服务器
自定义中间件类
- 在应用的目录里面创建middleware.py
- 在该文件当中创建中间件类-->类里面创建中间件函数
- 在setting.py中配置中间件MIDDLEWARE_CLASSES里面添加
函数调用顺序说明:
- __init__ --服务启动接受第一个url请求调用
- process_request --产生request对象,url匹配之前调用
- prosess_view --url匹配之后,视图函数之前调用
- prosess_response --视图函数调用完成之后调用,内容返回给浏览器之前调用
- prosess_exception --视图函数内部发生异常的时候调用
注意
调用顺序:当有多个异常类的时候会全部调用,调用顺序与注册顺序相反
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
class BlockedIPMiddleWare(): """创建阻止中间件的类""" def process_view(self, request, func_view, *view_args, **view_kwargs): """会在url配置之后函数调用之前调用""" addr = request.META['REMOTE_ADDR'] if addr == '127.0.0.1': return HttpResponse('middleware block!!!')
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
class TestMiddleWare(): """创建测试的中间件类""" def __init__(self): print('----init----') def process_request(self, request): print('----process_request----') # return HttpResponse('--process_request--') def process_view(self, request, view_func, *view_args, **view_kwargs): print('----process_view----') # return HttpResponse('--process_view--') def process_response(self, request, response): print('----process_response----') # return HttpResponse('--process_response--hello--kay--') return response # 如果在执行中间件的过程当中返回了httpResponse对象都会调用 # process_response()这个函数 # 只要返回httpResponsedui对象就会调用
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
class ExceptionTestMiddleWare(object): """异常中间件类""" def process_exception(self, request, exception): print('----exception_1----') print(exception) # 参数exception返回的是异常对象
上传照片
配置上传图片过程:
- 在setting.py里面做以下配置:
MEDIA_ROOT=os.path.join(BASE_DIR,"static/media")
- 在static路径下创建media文件夹
- 在创建的media文件夹下创建booktest文件夹用于保存booktest应用中视图上传的照片
- 创建包含图片的模型类
class PicTest(models.Model): """创建上传图片的模型类""" gpic = models.ImageField(upload_to='booktest') # 指定上传图片的路径
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
from django.conf import settings def upload_action(request): """上传图片的函数""" # 1.接受上传的文件 pic = request.FILES.get('pic') # print(pic.chunks) # 2.拼接保存的路径 save_path = "%s/booktest/%s" % (settings.MEDIA_ROOT, pic.name) # 3.打开文件 # save_file = open(save_path, 'wb') # save_file.close() # 4.快捷方法 with open(save_path, 'wb') as sava_file: # 5.传递过来的内容是分块的, 所以要遍历写 for file in pic.chunks(): # 6.写数据 sava_file.write(file) # 保存到数据库 p = PicTest() p.gpic = 'booktest/%s' % pic.name p.save() return HttpResponse('ok')
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<form action="/upload_action/" method="post" enctype="multipart/form-data"> {% csrf_token %} <input type="file" name="pic"> <input type="submit" value="上传"> </form>
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
def use_pic(request): """使用数据库本地的图片 1.从数据查找出图片对应的照片的路径 2.返回给http页面 3.在http页面当中加载 """ pic_path = PicTest.objects.get(id=1) print(pic_path.gpic) return render(request, 'booktest/use_pic.html', {"pic_path": pic_path.gpic})
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<img src="/static/media/{{ pic_path }}" alt="">
使用的配置方法上传图片
- 在项目的setting.py添加配置
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
TEMPLATES = [ { 'BACKEND': 'django.template.backends.django.DjangoTemplates', 'DIRS': [os.path.join(BASE_DIR, 'templates')] , 'APP_DIRS': True, 'OPTIONS': { 'context_processors': [ 'django.template.context_processors.debug', 'django.template.context_processors.request', 'django.contrib.auth.context_processors.auth', 'django.contrib.messages.context_processors.messages', # 1.添加本项 'django.template.context_processors.media' ], }, }, ] # 2.添加本项 MEDIA_URL = '/static/media/'
- 在模板当中使用
<img src="{{ MEDIA_URL }}{{ pic_path }}" alt="">
分页
Django提供了数据分页的类,这些类被定义在django/core/paginator.py中。 对象Paginator用于对列进行一页n条数据的分页运算。对象Page用于表示第m页的数据。
paginator对象
- 方法init(列表,int):返回分页对象,参数为列表数据,每面数据的条数。
- 属性count:返回对象总数。
- 属性num_pages:返回页面总数。
- 属性page_range:返回页码列表,从1开始,例如[1, 2, 3, 4]。
- 方法page(m):返回Page对象,表示第m页的数据,下标以1开始。
Page对象
- 调用Paginator对象的page()方法返回Page对象,不需要手动构造。
- 属性object_list:返回当前页对象的列表。
- 属性number:返回当前是第几页,从1开始。
- 属性paginator:当前页对应的Paginator对象。
- 方法has_next():如果有下一页返回True。
- 方法has_previous():如果有上一页返回True。
- 方法len():返回当前页面对象的个数。
- 迭代页面对象:访问当前页面中的每个对象。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
def show_prov(request, index): """显示所有的省级地区 1.创建分页的对象 2.获取第一页的内容 3.获取所有的页码内容显示到html页面上 4.处理点击更新显示的内容 """ areas = AreaInfo.objects.filter(aparent__isnull=True) # areas分页的内容 每10个分一页 创建分页的对象 paginator = Paginator(areas, 10) # 总共有多少页的页码 page_list = paginator.page_range # 获取第一页的内容 # 判断如果url为show_prov的时候匹配不到数字则为空所以进行判断一下 如果为空就显示第一页 if not index: index = 1 page = paginator.page(index) # 下一页的数子 # 给模板传递下一页的页码数 next_index = int(index) + 1 # 给模板传递上一页的页码数 previous_index = int(index) - 1 return render(request, 'booktest/page_test.html', {'page': page, 'page_list': page_list, "next_index": next_index, 'previous_index': previous_index})
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<body> <ul> {% for area in page %} <li>{{ area.atitle }}</li> {% endfor %} </ul> {# 如果有下一页则反回True #} {% if page.has_previous %} <a href="/show_prov{{ previous_index }}">上一页</a> {% endif %} {% for page_index in page_list %} {% comment %} page.number 返回当前的页面数 根据page判断是否还有下一个页面/上一页的选项 {% endcomment %} {% if page_index == page.number %} {{ page_index }} {% else %} <a href="/show_prov{{ page_index }}">{{ page_index }}</a> {% endif %} {% endfor %} {# 如果有下一页则反回True #} {% if page.has_next %} <a href="/show_prov{{ next_index }}">下一页</a> {% endif %} </body>
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
# 位置参数可有可无 url(r'^show_prov(\d*)/$', views.show_prov)