07-Django高级使用

一、静态文件

  • 简述
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 = [...]就中间件。

  • 方法执行


    中间件方法执行.png
  • 自定义中间件并使用

在工程目录下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);
                }
            }
        });
    });
});

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 202,607评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,047评论 2 379
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 149,496评论 0 335
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,405评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,400评论 5 364
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,479评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,883评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,535评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,743评论 1 295
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,544评论 2 319
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,612评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,309评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,881评论 3 306
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,891评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,136评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,783评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,316评论 2 342

推荐阅读更多精彩内容

  • 面试报名 4月18日—21日 面试考试 5月20日—21日
    猫七_698b阅读 80评论 0 0
  • 这个暑假我去了,老家。我们做了很长时间的车。到了那后我就去我外婆家。坐一坐,玩一会儿,然后就在那住了下来 还有我奶...
  • 爱情,刚开始或许是一种吸引,一种外貌的吸引,久而久之,便是一种舒适。没有刻意的讨好,没有刻意的委屈。
    冯凡平阅读 171评论 0 1
  • 【青春校园】我不怕孤身一人,只怕没有你(目录) 璇子本来想到了搭上地铁之后再跟陈辰讲她下班的消息的,所以陈辰发信息...
    薄小荷阅读 266评论 8 7