一、静态文件
- 简述
CSS、JS、JSON、图片、字体文件...
- 配置
settings.py
STATIC_URL='/static/'
STATICFILES_DIRS = [
os.path.join(BASE_DIR, 'static'),
]
- 示例
{% load static %}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>饿了吗 | 首页</title>
<link rel="stylesheet" type="text/css" href="{% static 'elema/css/style.css' %}"/>
<script type="text/javascript" src="{% static 'elema/js/jquery-3.1.1.min.js' %}"></script>
<script type="text/javascript" src="{% static 'elema/js/index.js' %}"></script>
</head>
<body>
<h1>饿了吗?</h1>
<img src="{% static 'elema/img/1.jpeg' %}">
</body>
</html>
在项目文件中创建static,并创建对应的应用目录,在应用目录里面添加例如js、img、css等目录
二、中间件
- 概述
中间件是一个用来处理Django的请求和响应的框架级别的钩子。
它是一个轻量、低级别的插件系统,用于在全局范围内改变Django的输入和输出。
每个中间件组件都负责做一些特定的功能。
但是由于其影响的是全局,所以需要谨慎使用,使用不当会影响性能。
本质: 就是一个python类
应用场景: 统计、黑名单、白名单、反爬...
- 方法
- __init__
不需要传参,服务器响应第一个请求的时,会自动调用,用于确定是否启用中间件
- process_request(self,request)
在视图执行前调用(即分配url匹配视图之前),每个请求都会调用,返回None或HttpResponse对象
- process_view(self,request,view_func,view_args,view_kwargs)
调用视图之前执行,每个请求都会调用,返回None或HttpResponse对象
- process_templae_response(self,request,response)
在视图刚好执行完后调用,每个请求都会调用,返回None或HttpResponse对象
- process_response(self,request,response)
所有响应返回浏览器之前调用,每个请求都会调用,返回None或HttpResponse对象
- process_exception(self,request,exception)
当视图出现异常时调用,返回HttpResponse对象
备注: 为什么会返回HttpRespons对象?因为在请求进来后如果有问题,就可以不做后续处理,直接给客户端响应。
settings.py
中的MIDDLEWARE = [...]就中间件。
-
方法执行
自定义中间件并使用
在工程目录下middleware目录下创建应用目录
- 在middleware/elema中创建一个elemamiddleware.py
from django.utils.deprecation import MiddlewareMixin
class MyMiddle(MiddlewareMixin):
# 在视图执行前调用
def process_request(self,reqeust):
print('get请求,参数name: ', reqeust.GET.get('name'))
- 配置settings.py文件(即在MIDDLEWARE中添加上述文件的位置)
'middleware.elema.elemamiddleware.MyMiddle'
- 浏览器
http://127.0.0.1:8000/?name=zyz
- 效果
在终端中可以看到`get请求,参数name: zyz`
- 中间件(黑名单拦截)
# 拦截器,拦截他黑名单中的IP
class MyMiddle(MiddlewareMixin):
def process_request(self, request):
if request.META['REMOTE_ADDR'] in getattr(settings, 'BLOCKED_IPS', []):
return HttpResponse('<h1>Forbidden</h1>')
# settings.py中
BLOCKED_IPS = [ # IP黑名单
'192.168.0.100'
]
- 中间件(未登陆处理)
class MyMiddle(MiddlewareMixin):
def process_request(self, request):
# request.META['REMOTE_ADDR'] 请求的IP地址
if request.path !='/meituan/login/': # 检测如果不是登录的话
if "username" in request.COOKIES: # 已经登录不做任何处理
pass
else: # 未登录,重定向到登录页面
return HttpResponseRedirect('/meituan/login/')
三、上传图片
- 注意
- 文件上传时,文件数据存储在request.FILES属性中
- form表单要上传文件需要加 enctype="multipart/form-data"
- 上传文件必须是post请求
- 存储路径
- 在static目录下创建upfile目录用于存储接受上传的文件
- 配置settings.py文件
MDEIA_ROOT = os.path.join(BASE_DIR,'static/upfile')
- 示例
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>文件上传</title>
</head>
<body>
<form action="{% url 'elema:savefile' %}" method="post" enctype="multipart/form-data">
{% csrf_token %}
<input type="file" value="上传文件" name="file">
<input type="submit" value="上传">
</form>
</body>
</html>
# 文件上传
def upfile(request):
return render(request, 'elema/upfile.html')
# 文件保存
import os
from django.conf import settings # 导入settings.py
def savefile(request):
# 判断是否为POST
if request.method == 'POST':
# 获取文件内容
file = request.FILES['file']
# 文件保存路径
filepath = os.path.join(settings.MDEIA_ROOT,file.name)
# 文件写入
with open(filepath,'wb') as fp:
for info in file.chunks():
fp.write(info)
return HttpResponse('文件上传成功')
else:
return HttpResponse('文件上传失败')
四、分页
- Paginator创建对象
格式: Paginator(列表,每页个数)
返回值: 分页对象
- Paginator属性
count: 对象总数
num_pages: 页面总数
page_range: 页码列表(页码从1开始)
- Paginator方法
page(num): 获得一个Page对象,如果提供的页面不存在会抛出'InvalidPage'异常
- Paginator异常
InvalidPage: 当向page()传递是一个无效页码时抛出
PageNotAnInteger: 当向page()传递的不是一个整数时抛出
EmptyPage: 当向page()传递一个有效值,但该页面没有数据时抛出
- Page创建对象
Paginator对象的page()方法返回得到Page对象(不需要手动创建)
- Page属性
object_list: 当前页上所有的数据(对象)列表
number: 当前页的页码值
paginator: 当前page对象关联的paginator对象
- Page方法
has_next(): 判断是否有下一页,如果有返回True
has_previous(): 判断是否有上一页,如果有返回True
has_other_pages(): 判断是否有上一页或下一页,如果有返回True
next_page_number(): 返回下一页的页码,如果下一页不存在抛出InvalidPage异常
previous_page_number(): 返回上一页的页码,如果上一页不存在抛出InvalidPage异常
len(): 返回当前页的数据(对象)个数
- Paginator对象与Page对象关系
- 示例
# urls.py文件
url(r'^goodslist/(\d+)/$',views.goodslist, name='goodslist'), # 商品列表
# views.py文件
# 商品列表
from .models import Goods
from django.core.paginator import Paginator
def goodslist(request,page):
# 所有商品数据
alllist = Goods.objects.all()
# 10条数据为一页,划分总页数
# 分页对象
paginator = Paginator(list(alllist),10)
# 根据传入的页码得到Page对象
pageobj = paginator.page(page)
# return HttpResponse('page:'+page)
return render(request,'elema/goodslist.html',{'pageobj':pageobj})
# models.py文件
# 商品 模型类
class Goods(models.Model):
# 商品名称
name = models.CharField(max_length=20)
# 商品图片
icon = models.CharField(max_length=255)
# 商品价格
price = models.IntegerField()
# 商品描述
detail = models.CharField(max_length=255)
class Meta:
db_table = 'goods'
# 存储过程: 创建商品数据(产生批量数据)
# 第一步: 创建上述Goods模型类 【注意表名是goods】
# 第二步: 生成迁移文件,并执行迁移
# 第三步: 进入到对应的数据库中,检查表单结构是否一致
mysql> desc goods;
+--------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+--------+--------------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| name | varchar(20) | NO | | NULL | |
| icon | varchar(255) | NO | | NULL | |
| price | int(11) | NO | | NULL | |
| detail | varchar(255) | NO | | NULL | |
+--------+--------------+------+-----+---------+----------------+
# 第四步: 将图片 'cymbal.png'等,放置在'/static/img'目录
# 第五步: 创建 存储过程 添加到数据库中(复制到mysql终端中)
# insert into elema_goods(name,icon,price,detail) value(_name,_icon,_price,_detail)
delimiter //
create procedure add_goods(num int(4))
begin
# 定义变量
declare _i,_price,_temp int(4) default 0;
declare _name,_icon,_detail varchar(255) default '';
declare BASE_PATH varchar(255) default '/static/img/';
# 循环
while _i<num do
# 设置变量
set _temp = round(rand()*10000+1000);
set _name = concat(_temp,'-商品名称');
set _temp = round(rand()*5+1);
case _temp
when 1 then
set _icon = concat(BASE_PATH,'1.jpg');
when 2 then
set _icon = concat(BASE_PATH,'2.jpg');
when 3 then
set _icon = concat(BASE_PATH,'3.jpg');
when 4 then
set _icon = concat(BASE_PATH,'4.jpg');
when 5 then
set _icon = concat(BASE_PATH,'5.jpg');
when 6 then
set _icon = concat(BASE_PATH,'6.jpg');
else
set _icon = concat(BASE_PATH,'1.jpg');
end case;
set _temp = round(rand()*10000+1000);
set _price = _temp;
set _temp = round(rand()*10000+1000);
set _detail = concat(_temp,'-Apple/苹果 iPhone 7 Plus苹果7代7pluss国行美版三网5.5寸7p手机');
# 插入数据
insert into goods(name,icon,price,detail) value(_name,_icon,_price,_detail);
# 修改次数
set _i = _i + 1;
end while;
# 显示数据
select * from goods;
end
//
delimiter ;
# 第六步: 调用存储过程 【根据自己需求添加对应个数即可】
call add_goods(30);
# goodslist.html文件
{% load static %}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>饿了吗 | 商品列表</title>
<link rel="stylesheet" type="text/css" href="{% static 'elema/css/goodslist.css' %}">
</head>
<body>
<h1>当前页: {{pageobj.number}}</h1>
<!--显示内容-->
<ul class="content">
{% for goods in pageobj.object_list %}
<li>
<div>
<img src="{{goods.icon}}">
<span> {{goods.name}} - ¥{{goods.price}}</span>
</div>
<p> {{goods.detail}} </p>
</li>
{% endfor %}
</ul>
<!--分页页码-->
<ul class="pageview">
{% for index in pageobj.paginator.page_range %}
<!--当前页面-->
{% if index == pageobj.number %}
<li class="active"> {{index}} </li>
{% else %}
<li>
<a href="{% url 'elema:goodslist' index %}">{{index}}</a>
</li>
{% endif %}
{% endfor %}
</ul>
</body>
</html>
五、ajax请求
- 概述
网页中需要动态生成时,会向服务器请求对应JSON数据
- 示例
# urls.py文件
url(r'^goodsjson/$',views.goodsjson, name='goodsjson'), # 商品列表json数据操作页面(ajax操作)
url(r'^goodsinfo/$',views.goodsinfo, name='goodsinfo'), # 商品列表json数据
# views.py文件
# 商品列表json数据(ajax操作)
def goodsjson(request):
return render(request,'elema/goodsjson.html')
# 返回商品列表json数据
from django.http import JsonResponse
def goodsinfo(request):
# 所有商品数据
alllist = Goods.objects.all()
# 拼接成列表
list = []
for goods in alllist:
list.append({'name':goods.name,'price':goods.price})
return JsonResponse({'data':list})
# goodsjson.html文件
{% load static %}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>商品列表JSON数据</title>
<script type="text/javascript" src="{% static 'elema/js/jquery-3.1.1.min.js' %}"></script>
<script type="text/javascript" src="{% static 'elema/js/goodsjson.js' %}"></script>
</head>
<body>
<h1>商品信息列表</h1>
<button id="bt">显示商品列表</button>
</body>
</html>
# goodsjson.js文件
$(function(){
$('#bt').click(function(){
// jquery中ajax快捷操作
$.ajax({
type:"get",
url:"/elema/goodsinfo",
dataType: 'json',
success: function(data, status){
console.log(data);
// 获取返回的数据
var datasource = data['data'];
for(var i=0; i<datasource.length; i++){
var oP = document.createElement('p');
oP.innerHTML = datasource[i]['name'] + " ¥" + datasource[i]['price'];
document.body.appendChild(oP);
}
}
});
});
});