• django


    http 协议

    什么是wsgi

    请求路径

    def index(request):
        # 访问 http://127.0.0.1:8000/index/?age=12
    
        # path 是 /index/
        print(request.path)
        # path_info 是 /index/
        print(request.path_info)
        # /index/?age=12
        print(request.get_full_path())
        # 127.0.0.1:8000
        print(request.get_host())
        # 8000
        print(request.get_port())
        # http://127.0.0.1:8000/index/?age=12
        print(request.get_raw_uri())
        # False
        print(request.is_ajax())
        return render(request, 'index.html')

    常用内置filter

    1. length
    2. filesizeformat       --> 格式化文件大小的
    3. date:'Y-m-d H:i:s'   --> 格式化时间的
    4. slice
    5. safe                 --> XSS攻击(跨站脚本攻击)
    6. truncatechars:20     --> 截取字符,超过的用...表示
    7. default

    自定义filter, simple_tag, inclusion_tag

    在对应的app目录下创建一个名叫templatetags包,在这个包随便创建一个py文件,起名xx.py

    from django import template
    from django.utils.safestring import mark_safe
    
    register = template.Library()   # register的名字是固定的,不可改变
    @register.filter
    def add(x,y):
        return x + y
    
    @register.simple_tag
    def task(a, b, v):
        return a + b + v

    在前端调用方式

    <!DOCTYPE html>
    <html lang="en">
    <!-- load 可以放在任何位置,可以看做是import,import xx 中的 xx 不需要加引号  -->
    {% load xx %}
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
        <!-- filter 和 simple_tag 的调用方式不同 -->
        {{ 5|add:10 }}
        {% task 4 5 5 %}
    </body>
    </html>

    inclusion_tag

    @register.inclusion_tag('result.html')
    def show(a,b, c):
        lis = [a, b, c]
        # 返回一个字典
        return {'choices': lis}

    result.html

    <ul>
    {% for choice in choices %}
      <li> {{choice}} </li>
    {% endfor %}
    </ul>

    index.html 调用:{% show 1 2 3 %}

    管理器

    BookInfo.objects.all()->objects是一个什么东西呢?其实,BookInfo 是一个类,objects是类的属性,这个属性也是一个对象,而且django会默认帮每一个model都生成这样一个对象。
    当然,我们也可以重写这个对象。也就是说自定义管理器类。

    class BookInfoManager(models.Manager):
        def all(self):
            books = super(BookInfoManager, self).all()
            books = books.filter(is_del=0)
            return books
    
        def create_book(self):
            book = self.model(title='hello')
            book.save()
    
    # Create your models here.
    class BookInfo(models.Model):
        title = models.CharField(max_length=32)
        is_del = models.BooleanField(default=0)
    
        objects = BookInfoManager()


    自定义管理器类的应用场景:

    1. 改变查询的结果集: 比如调用BookInfo.books.all()返回的是没有删除的图书的数据。
    2. 添加额外的方法: 管理器类中定义一个方法帮我们操作模型类对应的数据表, 使用self.model()就可以创建一个跟自定义管理器对应的模型类对象。

    csrf

    def index(request):
        request_csrf_token = request.POST.get('csrfmiddlewaretoken')
        csrf_token = request.COOKIES.get('csrftoken')
        print(request_csrf_token, csrf_token, _sanitize_token(request_csrf_token))
        request_csrf_token = _sanitize_token(request_csrf_token)
        if request.method == 'POST':
            print(_compare_salted_tokens(request_csrf_token, csrf_token))
        return render(request, 'index.html')

    csrf 是在中间件的process_view 做的操作,详情请看源码,就是把cookie中的csrftoken和request提交过了的做比较,这种比较是需要先转换之后才能比较,而且调用的是特殊的比较方法而不是==。
    csrf 预防的是什么?第三方网站拿着浏览器的cookie去给"官方网站"的接口发数据,以此达到"黑客"的目的。按理说,因为浏览器的同源策略,第三方网站去发送请求的时候不应该带着之前"官方网站"存在
    浏览器的cookie呀,这是因为浏览器同时还规定,提交表单不受同源政策的限制

    404页面自定制

    要想自定制404页面,只需要在templates目录写一个404.html即可。

    django 分页

    django cookie和session

    cookie的特点:

    1. 以键值对方式进行存储。
    2. 通过浏览器访问一个网站时,会将浏览器存储的跟网站相关的所有cookie信息发送给该网站的服务器。request.COOKIES
    3. cookie是基于域名安全的,访问不同域名只会把对应域名的cookie发送过去,不会发送别的网站的域名。www.baidu.com www.tudou.com
    4. cookie是有过期时间的,如果不指定,默认关闭浏览器之后cookie就会过期。

    获取cookie

    request.COOKIES['key']
    request.get_signed_cookie(key, default=RAISE_ERROR, salt='', max_age=None)
        参数:
            default: 默认值
               salt: 加密盐
            max_age: 后台控制过期时间

    设置cookie

    rep = HttpResponse(...) 或 rep = render(request, ...)
     
    rep.set_cookie(key,value,...)
    rep.set_signed_cookie(key,value,salt='加密盐',...)
        参数:
            key,              键
            value='',         值
            max_age=None,     超时时间
            expires=None,     超时时间(IE requires expires, so set it if hasn't been already.)
            path='/',         Cookie生效的路径,/ 表示根路径,特殊的:跟路径的cookie可以被任何url的页面访问
            domain=None,      Cookie生效的域名
            secure=False,     https传输
            httponly=False    只能http协议传输,无法被JavaScript获取(不是绝对,底层抓包可以获取到也可以被覆盖)

    这个函数里面,max_age就是cookie的超时时间,是以秒为单位的。也可以用expires设置绝对时间做为有效期,也可以是datetime.datetime的对象

    session

    session的特点:

    1. session是以键值对进行存储的。
    2. session依赖于cookie。唯一的标识码保存在sessionid cookie中。
    3. session也是有过期时间,如果不指定,默认两周就会过期。cookie是默认关闭浏览器就失效

    session的数据其实是通过base64加密,可以通过base64解密查看

    Django中默认支持Session,其内部提供了5种类型的Session供开发者使用:

    • 数据库(默认)
    • 缓存
    • 文件
    • 缓存+数据库
    • 加密cookie

    数据库

    Django默认支持Session,并且默认是将Session数据存储在数据库中,即:django_session 表中。
     
    a. 配置 settings.py
     
        SESSION_ENGINE = 'django.contrib.sessions.backends.db'   # 引擎(默认)
         
        SESSION_COOKIE_NAME = "sessionid"                       # Session的cookie保存在浏览器上时的key,即:sessionid=随机字符串(默认)
        SESSION_COOKIE_PATH = "/"                               # Session的cookie保存的路径(默认)
        SESSION_COOKIE_DOMAIN = None                             # Session的cookie保存的域名(默认)
        SESSION_COOKIE_SECURE = False                            # 是否Https传输cookie(默认)
        SESSION_COOKIE_HTTPONLY = True                           # 是否Session的cookie只支持http传输(默认)
        SESSION_COOKIE_AGE = 1209600                             # Session的cookie失效日期(2周)(默认)
        SESSION_EXPIRE_AT_BROWSER_CLOSE = False                  # 是否关闭浏览器使得Session过期(默认)
        SESSION_SAVE_EVERY_REQUEST = False                       # 是否每次请求都保存Session,默认修改之后才保存(默认),True表示每次关于session的操作session(除了获取session)都会重新设置过期时间
     
     
     
    b. 使用
     
        def index(request):
            # 获取、设置、删除Session中数据
            request.session['k1']
            request.session.get('k1',None)
            request.session['k1'] = 123
            request.session.setdefault('k1',123) # 存在则不设置
            del request.session['k1']
     
            # 所有 键、值、键值对
            request.session.keys()
            request.session.values()
            request.session.items()
            request.session.iterkeys()
            request.session.itervalues()
            request.session.iteritems()
     
     
            # 用户session的随机字符串
            request.session.session_key
            # 删除session数据,使其变为空字典
            request.session.clear()
            # 将所有Session失效日期小于当前日期的数据删除
            request.session.clear_expired()
     
            # 检查 用户session的随机字符串 在数据库中是否
            request.session.exists("session_key")
     
            # 删除当前用户的所有Session数据,删除数据库数据和cookie
            request.session.delete("session_key")
            # 清空数据库session数据,删除cookie
            request.session.flush()
     
            request.session.set_expiry(value)
                * 如果value是个整数,session会在些秒数后失效。
                * 如果value是个datatime或timedelta,session就会在这个时间后失效。
                * 如果value是0,用户关闭浏览器session就会失效。
                * 如果value是None,session会依赖全局session失效策略。

    缓存Session

    SESSION_ENGINE = 'django.contrib.sessions.backends.cache'  # 引擎
    SESSION_CACHE_ALIAS = 'default'                            # 使用的缓存别名(默认内存缓存,也可以是memcache),此处别名依赖缓存的设置
    
    
    SESSION_COOKIE_NAME = "sessionid"                        # Session的cookie保存在浏览器上时的key,即:sessionid=随机字符串
    SESSION_COOKIE_PATH = "/"                                # Session的cookie保存的路径
    SESSION_COOKIE_DOMAIN = None                              # Session的cookie保存的域名
    SESSION_COOKIE_SECURE = False                             # 是否Https传输cookie
    SESSION_COOKIE_HTTPONLY = True                            # 是否Session的cookie只支持http传输
    SESSION_COOKIE_AGE = 1209600                              # Session的cookie失效日期(2周)
    SESSION_EXPIRE_AT_BROWSER_CLOSE = False                   # 是否关闭浏览器使得Session过期
    SESSION_SAVE_EVERY_REQUEST = False                        # 是否每次请求都保存Session,默认修改之后才保存

    缓存+数据库Session

    SESSION_ENGINE = 'django.contrib.sessions.backends.cached_db' # 引擎

    验证码

    def verify_code(request):
        # 引入随机函数模块
        import random
        # 定义变量,用于画面的背景色、宽、高 RGB
        bgcolor = (random.randrange(20, 100), random.randrange(
            20, 100), 255)
        width = 100
        height = 25
        # 创建画面对象
        im = Image.new('RGB', (width, height), bgcolor)
        # 创建画笔对象
        draw = ImageDraw.Draw(im)
        # 调用画笔的point()函数绘制噪点
        for i in range(0, 100):
            xy = (random.randrange(0, width), random.randrange(0, height))
            fill = (random.randrange(0, 255), 255, random.randrange(0, 255))
            draw.point(xy, fill=fill)
    
        # 定义验证码的备选值
        str1 = 'ABCD123EFGHIJK456LMNOPQRS789TUVWXYZ0'
        # 随机选取4个值作为验证码
        rand_str = ''
        for i in range(0, 4):
            rand_str += str1[random.randrange(0, len(str1))]
    
        # 构造字体对象,ubuntu的字体路径为“/usr/share/fonts/truetype/freefont”
        font = ImageFont.truetype('FreeMono.ttf', 23)
        # 构造字体颜色
        fontcolor = (255, random.randrange(0, 255), random.randrange(0, 255))
        # 绘制4个字
        draw.text((5, 2), rand_str[0], font=font, fill=fontcolor)
        draw.text((25, 2), rand_str[1], font=font, fill=fontcolor)
        draw.text((50, 2), rand_str[2], font=font, fill=fontcolor)
        draw.text((75, 2), rand_str[3], font=font, fill=fontcolor)
        # 释放画笔
        del draw
        # 存入session,用于做进一步验证
        request.session['verifycode'] = rand_str
        # 内存文件操作
        buf = BytesIO()
        # 将图片保存在内存中,文件类型为png
        im.save(buf, 'png')
        # 将内存中的图片数据返回给客户端,MIME类型为图片png
        return HttpResponse(buf.getvalue(), 'image/png')

    django 上传文件

    request对象有一个FILES的属性,类似于字典,通过request.FILES可以获取上传文件的处理对象。
    在django中,上传文件不大于2.5M,文件放在内存中。上传文件大于2.5M,文件内容写到一个临时文件中,防止占用过大内存
    Django处理上传文件的两个类:
    FILE_UPLOAD_HANDLERS= ("django.core.files.uploadhandler.MemoryFileUploadHandler","django.core.files.uploadhandler.TemporaryFileUploadHandler")

    django 内置分页

    后端views.py

    def show_area(request, pindex):
        '''分页'''
        # 1.查询出所有省级地区的信息
        areas = AreaInfo.objects.filter(aParent__isnull=True)
        # 2. 分页,每页显示10条
        paginator = Paginator(areas, 10)
    
        # 3. 获取第pindex页的内容
        if pindex == '':
            # 默认取第一页的内容
            pindex = 1
        else:
            pindex = int(pindex)
        # page是Page类的实例对象
        page = paginator.page(pindex)
    
        # 4.使用模板
        return render(request, 'booktest/show_area.html', {'page':page})

    booktest/show_area.html

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>分页</title>
    </head>
    <body>
    <ul>
        {# 遍历获取每一条数据 #}
        {#  {% for area in page.object_list %}#}
        {% for area in page %}
            <li>{{ area.atitle }}</li>
        {% endfor %}
    </ul>
    {# 判断是否有上一页 #}
    {% if page.has_previous %}
        <a href="/show_area{{ page.previous_page_number }}">&lt;上一页</a>
    {% endif %}
    
    {# 遍历显示页码的链接 #}
    {% for pindex in page.paginator.page_range %}
        {# 判断是否是当前页 #}
        {% if pindex == page.number %}
            {{ pindex }}
        {% else %}
            <a href="/show_area{{ pindex }}">{{ pindex }}</a>
        {% endif %}
    {% endfor %}
    
    {# 判断是否有下一页 #}
    {% if page.has_next %}
        <a href="/show_area{{ page.next_page_number }}">下一页&gt;</a>
    {% endif %}
    </body>
    </html>

    序列化

    from django.core import serializers
    
    ret = models.BookInfo.objects.all()
    # '[{"model": "app01.bookinfo", "pk": 1, "fields": {"title": "hello", "is_del": false}}, {"model": "app01.bookinfo", "pk": 2, "fields": {"title": "world"
    # , "is_del": false}}]'
    data = serializers.serialize("json", ret)
    import json
    ret = models.BookInfo.objects.values('title')
    ret = list(ret)
    # '[{"title": "hello"}, {"title": "world"}]'
    json.dumps(ret)

    自定义json类

    import json
    from datetime import date
    from datetime import datetime
    
    """
    datetime 常用方法:
    datetime.datetime.replace()
    datetime.datetime.strftime():由日期格式转化为字符串格式
    datetime.datetime.now().strftime('%b-%d-%Y %H:%M:%S')
      'Apr-16-2017 21:01:35'
    
    datetime.datetime.strptime():由字符串格式转化为日期格式
    datetime.datetime.strptime('Apr-16-2017 21:01:35', '%b-%d-%Y %H:%M:%S')
    
    time1 = datetime.datetime(2016, 10, 20)
    time2 = datetime.datetime(2015, 11, 2)
    
    # 计算天数差值
    print(time1-time2).days
    
    # 计算两个日期之间相隔的秒数
    print (time1-time2).total_seconds()
    """
    
    class JsonCustomEncoder(json.JSONEncoder):
        def default(self, field):
            if isinstance(field, datetime):
                return field.strftime('%Y-%m-%d %H:%M:%S')
            elif isinstance(field, date):
                return field.strftime('%Y-%m-%d')
            else:
                return json.JSONEncoder.default(self, field)
    
    d = [datetime.now()]
    ds = json.dumps(d, cls=JsonCustomEncoder)
    # ["2018-09-07 14:48:55"]
    print(ds)

    上下文

    中间件是在用户请求到响应的过程中去加入一些额外的逻辑功能.上下文是给所有的模板增加变量,例子中给模板增加了一个myuser的变量.

    #1、在项目目录下创建一个xx.py文件(一般取名为processcontent.py)
    
    #2、在该文件中添加函数
    
    from test22.models import User
    def my_user(request):
        username = request.session.get('username','未登录') #获取session的username
        user = User.objects.filter(username=username).first() #验证数据库是否有这个username
        if user:
            return {'my_user':user.username} #返回的必须是字典类型
        else:
            return {'my_user':'游客'}
    
    #3、注册
    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',
                    'myblog.myprocesscontent.my_user', #项目名-py文件名-函数名(这一条就是注册)
                ],
            },
        },
    ]
  • 相关阅读:
    sys模块
    反射
    动态导入模块
    类的静态属性
    多态
    继承
    组合
    linux系统各个子目录的内容
    mysql安装
    Docker 数据卷操作
  • 原文地址:https://www.cnblogs.com/guofeng-1016/p/10716871.html
Copyright © 2020-2023  润新知