Django基础

一:安装django

首先创建虚拟环境并进入虚拟环境(https://blog.csdn.net/pcn01/article/details/103819684

pip install django==2.1.7     # 默认下载最新版本

创建django项目:

django-admin startproject dailyfresh

创建应用命令如下:

python manage.py startapp booktest

二:路由层

Django路由层

2.1 path与re_path函数

在新版本Django2.x中,url的路由表示用path和re_path代替,模块的导入由django1.x版本的from django.conf.urls import url,include变成现在的Django2.x中的from django.urls import path, re_path, include
path函数的定义为:path(route, view, name = None, kwargs = None)

path('book_detail/<book_id>/', views.book_detail),   # 默认为str转换器;视图函数中接收参数必须为:book_id
path('book/publisher/<int:p_id>', views.publisher),  # 指定p_id参数为int类型
re_path(r'^user/', include('user.urls')),
re_path(r'^login$', views.login),
# r 表示转义
# ^ 严格的开头
# $ 严格的结尾

在浏览器中输入的URL,哪些部分参与正则匹配?
http://ip:port/和get post参数不参与正则匹配
Django基础

2.2 url的反向解析

第一种写法是在project urls中指定app_name与实例命名空间

path('user/', include(('user.urls', 'user'), namespace = 'user')),
# 如果指定实例命名空间,那么前提是必须要先指定应用命名空间

第二种写法是在project urls中指定实例命名空间,然后在app urls中指定app_name

path('book/', include('book.urls', namespace = 'book')

app url中指定app_name:

app_name = 'book'
urlpatterns = [
    path('', views.index, name = 'index'),
]

视图函数中反转url

def login(request):
    username = request.GET.get('username')
    if username:
        return redirect(reverse('book:index')
    else:
        return HttpResponse('this is user login page')
# return redirect(reverse('book:index', args=(111,222)) 
# return redirect(reverse('book:index', kwargs={"key1":value1....})  # 应用有名分组,按照关键字传参   

HTML里的反向:

{%url '路由别名' 2019 12 %}
{%url '路由别名' year=2019 month=12 %}

三:视图层

Django视图层

3.1 HttpRequest对象属性

视图函数中的request就是HttpRequest类的对象;request包含浏览器请求的信息,服务器接收到http协议的请求后,会根据报文创建HttpRequest对象,这个对象不需要我们创建,直接使用服务器构造好的对象就可以。视图的第一个参数必须是HttpRequest对象,在django.http模块中定义了HttpRequest对象的API。

1.HttpRequest.GET
	# 一个类似于字典的对象,包含 HTTP GET 的所有参数。详情请参考 QueryDict 对象。
2.HttpRequest.POST
  # 一个类似于字典的对象,如果请求中包含表单数据,则将这些数据封装成 QueryDict 对象。
  # POST 请求可以带有空的 POST 字典 —— 如果通过 HTTP POST 方法发送一个表单,但是表单中没有任何的数据,QueryDict 对象依然会被创建。因此,不应该使用 if request.POST  来检查使用的是否是POST 方法;应该使用 if request.method == "POST"
  # 另外:如果使用 POST 上传文件的话,文件信息将包含在 FILES 属性中。
   # 注意:键值对的值是多个的时候,比如checkbox类型的input标签,select标签,需要用:request.POST.getlist("hobby")

3.HttpRequest.body
  # 一个字符串,代表请求报文的主体。在处理非 HTTP 形式的报文时非常有用,例如:二进制图片、XML,Json等。但是,如果要处理表单数据的时候,推荐还是使用 HttpRequest.POST 。

4.HttpRequest.path
  # 一个字符串,表示请求的路径组件(不含域名)。例如:"/music/bands/the_beatles/"
  
5.HttpRequest.method
  # 一个字符串,表示请求使用的HTTP 方法。必须使用大写。例如:"GET"、"POST"

6.HttpRequest.encoding
  # 一个字符串,表示提交的数据的编码方式(如果为 None 则表示使用 DEFAULT_CHARSET 的设置,默认为 'utf-8')。
    # 这个属性是可写的,你可以修改它来修改访问表单数据使用的编码。
   # 接下来对属性的任何访问(例如从 GET 或 POST 中读取数据)将使用新的 encoding 值。
   # 如果你知道表单数据的编码不是 DEFAULT_CHARSET ,则使用它。

7.HttpRequest.META

8.HttpRequest.FILES

9.HttpRequest.COOKIES

10.HttpRequest.session

11.HttpRequest.user(用户认证组件下使用)

12.HttpRequest.get_full_path()
  返回 path,如果可以将加上查询字符串。
  例如:"/music/bands/the_beatles/?print=true"

13.HttpRequest.is_ajax()
  如果请求是通过XMLHttpRequest 发起的,则返回True,方法是检查 HTTP_X_REQUESTED_WITH 相应的首部是否是字符串'XMLHttpRequest'。
  大部分现代的 JavaScript 库都会发送这个头部。如果你编写自己的 XMLHttpRequest 调用(在浏览器端),你必须手工设置这个值来让 is_ajax() 可以工作。
  如果一个响应需要根据请求是否是通过AJAX 发起的,并且你正在使用某种形式的缓存例如Django 的 cache middleware,
   你应该使用 vary_on_headers('HTTP_X_REQUESTED_WITH') 装饰你的视图以让响应能够正确地缓存。

3.2 HttpResponse对象

响应对象主要有三种形式(响应三剑客):

HttpResponse()
render()
redirect()

HttpResponse()括号内直接跟一个具体的字符串作为响应体,比较直接很简单

四:模板层

4.1 模板变量

在 Django 模板中遍历复杂数据结构的关键是句点字符, 语法:

{{ var_name }}

views.py:

def index(request):
    import datetime
    s="hello"
    l=[111,222,333]    # 列表
    dic={"name":"yuan","age":18}  # 字典
    date = datetime.date(1993, 5, 2)   # 日期对象
 
    class Person(object):
        def __init__(self,name):
            self.name=name
 
    person_yuan=Person("yuan")  # 自定义类对象
    person_egon=Person("egon")
    person_alex=Person("alex")
    person_list=[person_yuan,person_egon,person_alex]
    return render(request,"index.html",{"l":l,"dic":dic,"date":date,"person_list":person_list})

template:

<h4>{{s}}</h4>
<h4>列表:{{ l.0 }}</h4>
<h4>列表:{{ l.2 }}</h4>
<h4>字典:{{ dic.name }}</h4>
<h4>日期:{{ date.year }}</h4>
<h4>类对象列表:{{ person_list.0.name }}</h4>

注意:句点符也可以用来引用对象的方法(无参数方法):

<h4>字典:{{ dic.name.upper }}</h4>

模板变量的解析顺序:如 {{ book.btitle }}
1:首先把book当成一个字典,把btitle当成键名,进行取值 book[‘btitle’]
2:如果上面取不到值,把book当成一个对象,把btitle当成属性,进行取值 book.title
3:如果2取不到值,把book当成一个对象,把btitle当成对象的方法,进行取值 book.title
如果解析失败,则产生内容时用空字符串填充模板变量
使用模板变量时,点前面的可以是一个字典,可以是一个对象,还可以是一个列表

4.2 模板语法之过滤器

{{ value|default:"nothing" }}	# 如果一个变量是false或者为空,使用给定的默认值。否则,使用变量的值
{{ value|length }}				# 返回值的长度。它对字符串和列表都起作用
{{ value|filesizeformat }}		# 将值格式化为一个 “人类可读的” 文件尺寸 (例如 '13 KB', '4.1 MB', '102 bytes', 等等)
{{ value|date:"Y-m-d" }} 		# 格式化时间
{{ value|truncatechars:10 }}	# 如果字符串字符多于指定的字符数量,那么会被截断。截断的字符串将以可翻译的省略号序列(“...”)结尾
{{ value|safe }}				
# Django的模板中会对HTML标签和JS等语法标签进行自动转义,原因显而易见,这样是为了安全。但是有的时候我们可能不希望这些HTML元素被转义,比如我们做一个内容管理系统,后台添加的文章中是经过修饰的,这些修饰可能是通过一个类似于FCKeditor编辑加注了HTML修饰符的文本,如果自动转义的话显示的就是保护HTML标签的源文件。为了在Django中关闭HTML的自动转义有两种方式,如果是一个单独的变量我们可以通过过滤器“|safe”的方式告诉Django这段代码是安全的不必转义

4.3 模板标签

标签看起来像是这样的: {% tag %}。标签比变量更加复杂:一些在输出中创建文本,一些通过循环或逻辑来控制流程,一些加载其后的变量将使用到的额外信息到模版中。一些标签需要开始和结束标签 (例如{% tag %} …标签 内容 … {% endtag %})。

for标签:
遍历每一个元素:

{% for person in person_list %}
    <p>{{ person.name }}</p>
{% endfor %}

可以利用{% for obj in list reversed %}反向完成循环。

遍历一个字典:

{% for key,val in dic.items %}
    <p>{{ key }}:{{ val }}</p>
{% endfor %}

注:循环序号可以通过{{forloop}}显示

forloop.counter            The current iteration of the loop (1-indexed)
forloop.counter0           The current iteration of the loop (0-indexed)
forloop.revcounter         The number of iterations from the end of the loop (1-indexed)
forloop.revcounter0        The number of iterations from the end of the loop (0-indexed)
forloop.first              True if this is the first time through the loop
forloop.last               True if this is the last time through the loop

for … empty:
for 标签带有一个可选的{% empty %} 从句,以便在给出的组是空的或者没有被找到时,可以有所操作。

{% for person in person_list %}
    <p>{{ person.name }}</p>

{% empty %}
    <p>sorry,no person here</p>
{% endfor %}

if 标签:
{% if %}会对一个变量求值,如果它的值是“True”(存在、不为空、且不是boolean类型的false值),对应的内容块会输出。

{% if num > 100 or num < 0 %}
    <p>无效</p>
{% elif num > 80 and num < 100 %}
    <p>优秀</p>
{% else %}
    <p>凑活吧</p>
{% endif %}

with:
使用一个简单地名字缓存一个复杂的变量,当你需要使用一个“昂贵的”方法(比如访问数据库)很多次的时候是非常有用的

{% with total=business.employees.count %}
    {{ total }} employee{{ total|pluralize }}
{% endwith %}

4.4 静态文件的载入

{% load staticfiles %}
<head>
   <meta http-equiv="Content-Type" content="text/html;charset=UTF-8">
   <title>天天生鲜-注册</title>
   <link rel="stylesheet" type="text/css" href="{% static 'css/reset.css' %}">
</head>

如果不想每次都在模板中写 {% load staticfiles %} 代码,可以在settings配置文件中添加以下代码:

TEMPLATES = [
    {
......................
        'OPTIONS': {
            'context_processors': [
                .......................
            ],
            'builtins': ['django.templatetags.static'] # 加入此行代码
        },
    },
]

4.5 自定义过滤器

过滤器的本质就是python函数;自定义的过滤器至少要有一个参数,最多两个参数
1:首先在项目目录下新建一个包,名为:templatetags,该目录名是固定的
2:在templatetags目录下新建filters.py文件,该文件名可任意取

from django.template import Library
register = Library()
@register.filter  # 必须使用register.filter装饰下面自定义的函数
def mod(num):
    # 判断num是否为偶数
    return num % 2 == 0

3:模板文件中使用自定义的过滤器

<!DOCTYPE html>
<html lang="en">
{% load filters %}   # 导入过滤器,filters为自定义过滤器的文件名,该文件下所有的过滤器都导入了
.........................
<ul>
    {% for book in books %}
        {% if book.id|mod %}  # 管道符会将前面的值传递给mod函数
        <li style="background:green;">{{ forloop.counter }} : {{ book.btitle }}</li>
        {% else %}
        <li style="background:red;">{{ forloop.counter }} : {{ book.btitle }}</li>
        {% endif %}
    {% endfor %}
</ul>
..................

4:如果自定义过滤器中有多个参数,如:

from django.template import Library
register = Library()
@register.filter
def mod(num):
    # 判断num是否为偶数
    return num % 2 == 0
@register.filter
def mod_val(num, val):
    '''判断num是否能被val整除'''
    return num % val == 0

模板中使用方法:

<ul>
    {% for book in books %}
        {% if book.id|mod_val:2 %}   # 第二个参数自己传递给mod_val函数
        <li style="background:green;">{{ forloop.counter }} : {{ book.btitle }}</li>
        {% else %}
        <li style="background:red;">{{ forloop.counter }} : {{ book.btitle }}</li>
        {% endif %}
    {% endfor %}
</ul>

4.6 verbatim标签

verbatim 标签:默认在 DTL 模板中是会去解析那些特殊字符的。比如 {% 和 %} 以及 {{ 等。如果你在某个代码片段中不想使用 DTL 的解析引擎。那么你可以把这个代码片段放在 verbatim 标签中
verbatim标签

五:AJAX请求

JsonResponse对象的content-type为’application/json’

<script>
    $(function() {
        $('#btnLogin').click(function() {
            username = $('#username').val();
            password = $('#password').val();
            $.ajax({
                'url': '/login',
                'type': 'post',
                'data': {'username': username, 'password': password},
                'dataType': 'json'
            }).success(function(data) {
                console.log(data);
                if (data.res == 0) {
                    $('#message').show().html('用户名或密码错误')
                }else{
                    location.href = '/';
                }
            })
        })
    })
</script>

视图函数:

def login(request):
    if request.method == 'POST':
        username = request.POST.get('username')
        password = request.POST.get('password')
        if username == 'smart' and password == '123':
            return JsonResponse({'res': 1})
        else:
            return JsonResponse({'res': 0})
    return render(request, 'login.html')

六:状态保持

6.1 cookie

http协议是无状态的。下一次去访问一个页面时并不知道上一次对这个页面做了什么。
1:以键值对方式进行存储
2:通过浏览器访问一个网站时,会将浏览器存储的跟网站相关的所有cookie信息发送给该网站的服务器。request.COOKIES
3:cookie是基于域名安装的
4:cookie是有过期时间的,如果不指定,默认关闭浏览器之后cookie就会过期
设置COOKIE需要一个HttpResponse类的对象或者是它子类的对象
浏览器发给服务器的cookie,保存在request对象COOKIES中

def set_cookie(request):
    response = HttpResponse('设置cookie')
    response.set_cookie('num', 1, max_age = 14*24*3600)    # max_age设置过期时间:多长时间过期
    # response.set_cookie('num', 1, expires = datetime.now() + timedelta(days = 14))   # expires设置过期时间:什么时间点过期
    return response

def get_cookie(request):
    num = request.COOKIES['num']
    return HttpResponse(num)

6.2 session

session存储在服务器端
1:session是以键值对进行存储的
2:session依赖于cookie
3:session也是有过期时间,如果不指定,默认两周就会过期

def set_session(request):
    request.session['username'] = 'smart'
    request.session['age'] = 18
    return HttpResponse('设置session')

def get_session(request):
    username = request.session['username']
    age = request.session['age']    # 也可以使用get获取数据:request.session.get('age', 默认值)
    return HttpResponse(username + ':' + str(age))

####### session的其它操作 ##############
request.session.clear()    # 清除session,在存储中删除值部分
request.session.flush()    # 清除session,删除数据库的记录
del request.session['key'] # 删除某个键对应的值
request.session.has_key('islogin')    # 判断session中是否有islogin键

django将session入库
django将session入库
session_data为base64加密后的字符串

request.session.set_expiry(value)    # 设置session的过期时间
# value是一个整数,会话的session_id cookie将在value秒没有活动后过期
# value为0,那么用户会话的session_id cookie将在用户的浏览器关闭时过期
# value为None,那会会话的session_id cookie两周之后过期

cookie and session的应用场景:
cookie:记住用户名,安全性要求不高
session:涉及到安全性要求比较高的数据。银行卡账户,密码

七:中间件

Django中间件
Django中间件

7.1 自定义中间件

中间件可以定义五个方法,分别是:

process_request(self,request)
process_view(self, request, view_func, view_args, view_kwargs)
process_exception(self, request, exception)
process_response(self, request, response)
process_template_response(self,request,response)(了解)

utils.middle.py文件:

from django.utils.deprecation import MiddlewareMixin

class MD1(MiddlewareMixin):

    def process_request(self, request):
        print('MD1下的process_request方法')

    def process_response(self, request, response):
        print('MD1下的process_response方法')
        return response         # 必须返回response对象

class MD2(MiddlewareMixin):

    def process_request(self, request):
        print('MD2下的process_request方法')

    def process_response(self, request, response):
        print('MD2下的process_response方法')
        return response

注册自定义中间件:

MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
.......................................
    'utils.middle.MD1',
    'utils.middle.MD2',
]

访问一个视图函数,输出结果 如下:

MD1下的process_request方法
MD2下的process_request方法
MD2下的process_response方法
MD1下的process_response方法
# 整个执行流程可看上图

八:Django流程

Django流程

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值