码迷,mamicode.com
首页 > 编程语言 > 详细

python之Django

时间:2019-09-28 00:44:15      阅读:116      评论:0      收藏:0      [点我收藏+]

标签:完整   建表   全路径   失败   函数返回   翻译   集合   字符   链式   

1 Django基础一之web框架的本质

Django 、Flask 这些就是Python语言的web 框架。

1.1web框架的本质

Web应用本质上就是一个socket服务端,而用户的浏览器就是一个socket客户端。

1.1.1什么是 Web 服务器?

平时我们都是通过浏览器(比如Chrome,Firefox等)上网的,当我们在浏览器的地址栏里输入地址后,会得到一个网页。

这个网页就是 web 服务器返回给我们的,而浏览器就称为客户端,当我们输入网址并按下回车后,就像web服务器发送了一个web请求。

这种模式成为 B/S 模式 ,即 Browse / Server 模式

在浏览器中输入地址、按回车后,按下F12 就是看到如下信息

技术图片

下面就让我们来目睹整个过程吧

  1. 建立连接:客户机通过TCP/IP协议建立到服务器的TCP连接。
  2. 请求过程:客户端向服务器发送HTTP协议请求包(Request),请求服务器里的资源文档。
  3. 应答过程:服务器向客户机发送HTTP协议应答包(Response),如果请求的资源包含有动态语言的内容,那么服务器会调用动态语言的解释引擎负责处理“动态内容”,并将处理得到的数据返回给客户端。由客户端解释HTML文档,在客户端屏幕上渲染图形结果。
  4. 关闭连接:客户机与服务器断开。

这里Request 和 Response 都需要遵守 HTTP 协议,关于 HTTP 协议的详细内容,可以读读《HTTP 权威指南》

但是实际中的 Web 服务器远远比上面示例的复杂的多,因为要考虑的因素实在是太多了,比如:

  • 缓存机制:讲一些经常被访问的页面缓存起来,提高响应速度;
  • 安全:防止黑客的各种攻击,比如 SYN Flood 攻击;
  • 并发处理:如何响应不同客户端同时发起的请求;
  • 日志:记录访问日至,方便做一些分析。

目前在UNIX和LINUX平台下使用最广泛的免费 Web 服务器有Apache和 Nginx 。而这些软件都是遵循遵守 HTTP 协议的。

所以可以称他们为HTTP服务器,只是可以通过HTTP协议语言的解析转换。

https://www.cnblogs.com/clschao/articles/9230431.html

1.1.2Web 应用程序?

Web 服务器接受 Http Request,返回 Response,很多时候 Response 并不是静态文件,因此需要有一个应用程序根据 Request 生成相应的 Response。这里的应用程序主要用来处理相关业务逻辑,读取或者更新数据库,根据不同 Request 返回相应的 Response。注意这里并不是 Web 服务器本身来做这件事,它只负责 Http 协议层面和一些诸如并发处理,安全,日志等相关的事情。

应用程序可以用各种语言编写(Java, PHP, Python, Ruby等),这个应用程序会从Web服务器接收客户端的请求,处理完成后,再返回响应给Web服务器,最后由Web服务器返回给客户端。整个架构如下:

对于所有的Web应用,本质上其实就是一个socket服务端,用户的浏览器其实就是一个socket客户端。

1.1.3Web 框架

? 框架,即framework,特指为解决一个开放性问题而设计的具有一定约束性的支撑结构,使用框架可以帮你快速开发特定的系统,简单地说,就是你用别人搭建好的舞台来做表演。

? 以 python web 框架 flask 为例,框架本身并不限定我们用哪种架构来组织我们的应用,不过其中一种比较经典的Web框架 Flask 采用了 MVC 架构,可以很好地支持以 MVC 方式组织应用。

  1. 用户输入 URL,客户端发送请求
  2. 控制器(Controller)首先会拿到请求
  3. 然后用模型(Models)从数据库取出所有需要的数据,进行必要的处理,将处理后的结果发送给 视图(View)
  4. 视图利用获取到的数据,进行渲染生成 Html Response返回给客户端。

1.2基于socket自定义web框架

待定

1.3 模板渲染JinJa2

1.4MVC和MTV框架

1.4.1MVC

Web服务器开发领域里著名的MVC模式,所谓MVC就是把Web应用分为模型(M),控制器(C)和视图(V)三层,他们之间以一种插件式的、松耦合的方式连接在一起,模型负责业务对象与数据库的映射(ORM),视图负责与用户的交互(页面),控制器接受用户的输入调用模型和视图完成用户的请求,其示意图如下所示:

技术图片

1.4.2MTV

 Django的MTV模式本质上和MVC是一样的,也是为了各组件间保持松耦合关系,只是定义上有些许不同,Django的MTV分别是值:

  • M 代表模型(Model): 负责业务对象和数据库的关系映射(ORM)。
  • T 代表模板 (Template):负责如何把页面展示给用户(html)。
  • V 代表视图(View): 负责业务逻辑,并在适当时候调用Model和Template。

  除了以上三层之外,还需要一个URL分发器,它的作用是将一个个URL的页面请求分发给不同的View处理,View再调用相应的Model和Template,MTV的响应模式如下所示:

  技术图片

  一般是用户通过浏览器向我们的服务器发起一个请求(request),这个请求回去访问视图函数,(如果不涉及到数据调用,那么这个时候视图函数返回一个模板也就是一个网页给用户),视图函数调用模型,模型去数据库查找数据,然后逐级返回,视图函数把返回的数据填充到模板中空格中,最后返回网页给用户。

1.5 Django下载安装 创建项目应用

1.5.1Django下载安装

1.5.1.1 cmd下载

第一种 cmd 输入python 进入 python解释器

输入pip3 install django==1.11.9
pip国内的一些镜像
阿里云 http://mirrors.aliyun.com/pypi/simple/
中国科技大学 https://pypi.mirrors.ustc.edu.cn/simple/
豆瓣(douban) http://pypi.douban.com/simple/
清华大学 https://pypi.tuna.tsinghua.edu.cn/simple/
中国科学技术大学 http://pypi.mirrors.ustc.edu.cn/simple/
临时使用:
可以在使用pip的时候在后面加上-i参数,指定pip源
修改源方法
pip3 install django==1.11.9

卸载djange
pip uninstall django

1.5.1.2pycham下载

File | Settings | Project: un1 | Project Interpreter
添加django
勾选这个Specify version  选择历史版本

技术图片

1.5.2创建djange项目

1.5.2.1pythcm创建

注意不要选择虚拟环境

技术图片

1.5.2.2终端创建

创建项目
    django-admin startproject mysite   创建了一个名为"mysite"的Django 项目
启动项目

启动项目
    python manage.py runserver  默认是127.0.0.1:8000
    python manage.py runserver 127.0.0.1  默认端口号是8000
    python manage.py runserver 127.0.0.1:8001 

当前目录下会生成mysite的工程,目录结构如下:(大家注意昂,pip下载下来的django你就理解成一个模块,而不是django项目,这个模块可以帮我们创建django项目)

?   技术图片

  • manage.py ----- Django项目里面的工具,通过它可以调用django shell和数据库,启动关闭项目与项目交互等,不管你将框架分了几个文件,必然有一个启动文件,其实他们本身就是一个文件。
  • settings.py ---- 包含了项目的默认设置,包括数据库信息,调试标志以及其他一些工作的变量。
  • urls.py ----- 负责把URL模式映射到应用程序。
  • wsgi.py ---- runserver命令就使用wsgiref模块做简单的web server,后面会看到renserver命令,所有与socket相关的内容都在这个文件里面了,目前不需要关注它。

1.5.3创建应用

python manage.py startapp blog   #通过执行manage.py文件来创建应用blog,执行这句话一定要注意,你应该在这个manage.py的文件所在目录下执行这句话,因为其他目录里面没有这个文件
python manage.py startapp blog2  #每个应用都有自己的目录,每个应用的目录下都有自己的views.py视图函数和models.py数据库操作相关的文件

技术图片

  我们现在只需要看其中两个文件

    models.py :之前我们写的那个名为model的文件就是创建表用的,这个文件就是存放与该app(应用)相关的表结构的

    views.py :存放与该app相关的视图函数的

1.6基于Django的简单小示例

第1步 先配置setting.py文件中的INSTALLED_APPS
第2步 配置urls.py文件 路径分发 
第3步 配置视图,views.py 写自己的逻辑 返回html页面 还是重定向 等等
第4步 创建 对应的html页面

注意点 from表单 不添提交地址就是原地址 我们可以通过请求方式get\post 进行逻辑判断

1.6.1配置setting.py

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'app01.apps.App01Config',#添加app01的应用
]

1.6.2配置配置url

from app01 import views
urlpatterns = [#只做路径匹配 不分post还是get
    url(r'^admin/', admin.site.urls),
    url(r'^login/', views.login),
    url(r'^login/(\d+)/(\d+)/', views.articles), #articles/2019/9/
]


 # 有名分组参数
    url(r'^articles/(?P<month>\d+)/(?P<year>\d+)/', views.articles), #articles/2019/9/
    #xx=2019  oo=9  关键字传参

1.6.3找到视图views.py写逻辑

request形参 对象 约定俗成 
HttpResponse可以返回字符串
redirect重定向

from django.shortcuts import render,HttpResponse
print(request.path)
def login(request):
    if request.method == 'POST':
        name = request.POST.get('username')  # 获取的是字符串用户输入的值
        pwd = request.POST.get('pwd')
        # print(name,pwd,'----------------------')
        if name == 'aa' and pwd == 'aa':
            return render(request, 'login2.html')
        else:
            return HttpResponse('登录失败!!')
    else:
        return render(request, 'login.html')#模板渲染 模板就是html页面 渲染就是字符串替换   第一个参数:request  第二个参数是html页面路径,
        
from django.shortcuts import render,HttpResponse,redirect
from django.urls import reverse

def home(request):
    return redirect(reverse('cs1'))

1.6.4创建login.html

如果action里面不写还是原页面 我们可以设置method进行逻辑判断

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>

<form action="" method="post">  <!-- http://127.0.0.1:8000 /login/    /login2/-->
    用户名:<input type="text" name="username">  <!-- http://127.0.0.1:8000/login/login2/ -->
    密码:<input type="text" name="pwd">
    <input type="submit">
</form>

</body>
{#<script src="jquery.js"></script>#}
</html>

2 Django基础二之URL路由系统

2.1HTTP协议

详细https://www.cnblogs.com/clschao/articles/9230431.html

http协议
请求信息格式
GET / HTTP/1.1   请求行
Host: 127.0.0.1:8003  请求头
Connection: keep-alive
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.100 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3
Accept-Encoding: gzip, deflate, br
Accept-Language: zh-CN,zh;q=0.9
#空行
请求数据  username=ziwen password=666


get请求 请求数据部分是没有数据的,get请求的数据在url上,在请求行里面,有大小限制,常见的get请求方式: 浏览器输入网址,a标签
post请求 请求数据在请求体(请求数据部分) ,数据没有大小限制, 常见方式:form表单提交数据

2.2MVC和MTV框架模式

MVC:
    M -- models 数据库相关
    V -- views  视图相关(逻辑)
    C -- controller url控制器(url分发器,路由分发)
django -- MTV
    M -- models 数据库相关
    T -- templates HTML相关 html就是模板
    V -- views  视图相关(逻辑)
    
    + controller url控制器(url分发器,路由分发)

django下载安装

下载
    pip3 install django==1.11.9 
    pip3 install django==1.11.9 -i http://xxxxxx  指定源
创建项目
    django-admin startproject mysite   创建了一个名为"mysite"的Django 项目
启动项目
    python manage.py runserver  默认是127.0.0.1:8000
    python manage.py runserver 127.0.0.1  默认端口号是8000
    python manage.py runserver 127.0.0.1:8001 
    

2.3django的url路由分发

    # url(r'^articles/(\d+)/(\d+)/', views.articles), #articles/2019/9/
    视图函数
        def articles(request,year,month):  # 位置参数 2019  9
            print(year,type(year)) #2019 <class 'str'>  #匹配出来的所有数据都是字符串
            print(month)

            return HttpResponse(year+'年'+ month +'月' +'所有文章')
        

    # 有名分组参数
    url(r'^articles/(?P<xx>\d+)/(?P<oo>\d+)/', views.articles), #articles/2019/9/
    #xx=2019  oo=9  关键字传参
    
    def articles(request,oo,xx):  # 关键字传参 2019  9
        print(xx,type(xx)) #2019 <class 'str'>  #匹配出来的所有数据都是字符串
        print(oo)
        return HttpResponse(xx+'年'+ oo +'月' +'所有文章')

3 Django基础三之视图函数

3.1视图

一个视图函数(类),简称视图,是一个简单的Python 函数(类),它接受Web请求并且返回Web响应。

响应可以是一张网页的HTML内容,一个重定向,一个404错误,一个XML文档,或者一张图片。

无论视图本身包含什么逻辑,都要返回响应。代码写在哪里也无所谓,只要它在你当前项目目录下面。除此之外没有更多的要求了

HTTPRequest对象就是咱们的视图函数的参数request

    # print(request)  #<WSGIRequest: GET '/home/'>
    # # print(dir(request))
    #
    # print(request.path) #/home/  纯路径
    # print(request.path_info) #/home/  纯路径
    # print(request.get_full_path()) #/home/?a=1&b=2  全路径(不包含ip地址和端口)

    # print(request.META)  #请求头相关数据,是一个字典

    # print(request.method)  #GET

    # print(request.GET)
    
    # print(request.POST)
    # print(request.body)  能够拿到请求数据部分的数据(post,get没有)

HTTPResponse对象

HTTPResponse('字符串')
render(request,'xx.html')

redirect 重定向#用法  redirect(路径) 示例:redirect('/index/')

3.2FBV和CBV 视图

3.2.1FBV(函数类)

FBV(function base views) 就是在视图里使用函数处理请求。

from django.shortcuts import render,HttpResponse,redirect
def cs(request):
    return redirect('/cs1/')  #重定向  redirect(路径)

3.2.2CBV(对象)

CBV(class base views) 就是在视图里使用类处理请求。

最后一步源码

 http_method_names = ['get', 'post', 'put', 'patch', 'delete', 'head', 'options', 'trace']

def dispatch(self, request, *args, **kwargs):
    # Try to dispatch to the right method; if a method doesn't exist,
    # defer to the error handler. Also defer to the error handler if the
    # request method isn't on the approved list.
    if request.method.lower() in self.http_method_names:#实现分发的
        handler = getattr(self, request.method.lower(), self.http_method_not_allowed)
    else:
        handler = self.http_method_not_allowed
    return handler(request, *args, **kwargs)

通过剖析源码 我们可以在分发前执行我们的逻辑

from django.views import View
class LoginView(View):
    # def dispatch(self, request, *args, **kwargs):
    #     print('xx请求来啦!!!!')请求来之前  但不知道是什么方法前执行
    #     ret = super().dispatch(request, *args, **kwargs)
    #     print('请求处理的逻辑已经结束啦!!!')
    #     return ret
    def get(self,request):  #处理get请求直接定义get方法,不需要自己判断请求方法了,源码中用dispatch方法中使用了反射来处理的
        print('小小小小')
        return render(request,'login.html')

    def post(self,request):
        print(request.POST)
        return HttpResponse('登录成功')

urls.py路由写法

url(r'^login/', views.LoginView.as_view()),

3.3视图类 加装饰器

3.3.1装饰器装饰FBV

FBV本身就是一个函数,所以和给普通的函数加装饰器无差

def wrapper(func):
    def inner(*args, **kwargs):
        start_time = time.time()
        ret = func(*args, **kwargs)
        end_time = time.time()
        print("used:", end_time-start_time)
        return ret
    return inner


# FBV版添加班级
@wrapper
def add_class(request):
    if request.method == "POST":
        class_name = request.POST.get("class_name")
        models.Classes.objects.create(name=class_name)
        return redirect("/class_list/")
    return render(request, "add_class.html")

3.3.2装饰器装饰CBV

类中的方法与独立函数不完全相同,因此不能直接将函数装饰器应用于类中的方法 ,我们需要先将其转换为方法装饰器。Django中提供了method_decorator装饰器用于将函数装饰器转换为方法装饰器。

第一步先引入模块from django.utils.decorators import method_decorator`
第2步 加语法糖@method_decorator(wrapper)`


from django.shortcuts import render,HttpResponse
from django.views import View
from django.utils.decorators import method_decorator
def wrapper(func):
    def inner(*args, **kwargs):
        print(11111)
        ret = func(*args, **kwargs)
        print(22222)
        return ret
    return inner

# @method_decorator(wrapper,name='get')  # 方式3给get加 用的不多
class LoginView(View):

    @method_decorator(wrapper)  #方式1
    def get(self,request):
        print('小小小小')
        return HttpResponse('登录成功')

    def post(self,request):
        print(request.POST)
        return HttpResponse('登录成功')

3.4request对象

Django会将这个对象自动传递给响应的视图函数,一般视图函数约定俗成地使用 request 参数承接这个对象。

 官方文档

 请求相关的常用值

  • path_info 返回用户访问url,不包括域名
  • method 请求中使用的HTTP方法的字符串表示,全大写表示。
  • GET 包含所有HTTP GET参数的类字典对象
  • POST 包含所有HTTP POST参数的类字典对象
  • body 请求体,byte类型 request.POST的数据就是从body里面提取到的

属性

当get请求输入网址http://127.0.0.1:8000/cs/??a=1&b=2

def cs(request):
    print(request)  #<WSGIRequest: GET '/cs/??a=1&b=2'>
    print(request.path) #/cs/ 纯路径
    print(request.path_info) #/cs/ 纯路径
    print(request.get_full_path())#/cs/??a=1&b=2全路径 (不包含ip地址和端口)
    print(request.META)  #请求头相关数据,是一个字典
    print(request.method)  #GET
    print(request.GET)#<QueryDict: {'?a': ['1'], 'b': ['2']}>
    print(request.POST)#<QueryDict: {}>
    print(request.body) #能够拿到请求数据部分的数据(post,get没有) b''
    return HttpResponse('666')

输入网址http://127.0.0.1:8000/cs/

def cs(request):
    print(request)  #<WSGIRequest: GET '/cs/??a=1&b=2'>
    print(request.path) #/cs/ 纯路径
    print(request.path_info) #/cs/ 纯路径
    print(request.get_full_path())#/cs/??a=1&b=2全路径 (不包含ip地址和端口)
    print(request.META)  #请求头相关数据,是一个字典
    print(request.method)  #POST
    print(request.GET)#<QueryDict: {}>
    print(request.POST)#<QueryDict: {'a': ['1'], 'b': ['2']}>
    print(request.body) # b'a=1&b=2'  能够拿到请求数据部分的数据(post,get没有) 
    return render(request,'cs.html')

a框输入1 b框输入2

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<form action="" method="post">
    a<input type="text" name="a">
    b<input type="text" name="b">
    <input type="submit">
</form>
</body>
</html>

3.5Response对象

from django.shortcuts import render,HttpResponse,redirect
HTTPResponse('字符串') #返回字符串
render(request,'xx.html')#返回html页面

redirect 重定向
def cs(request):
    return redirect('/cs1/')  #重定向  redirect(路径)

def cs1(request):
    return HttpResponse('666')

4 Django基础四之模板系统

4.1模板渲染的语法

模板渲染的官方文档

  关于模板渲染你只需要记两种特殊符号(语法):

  {{ }}和 {% %}

  变量相关的用{{}},逻辑相关的用{%%}。

{{ 变量 }}   {% 逻辑 %} -- 标签

4.2变量

在Django的模板语言中按此语法使用:{{ 变量名 }}。

当模版引擎遇到一个变量,它将计算这个变量,然后用结果替换掉它本身。 变量的命名包括任何字母数字以及下划线 ("_")的组合。 变量名称中不能有空格或标点符号。

我们可以利用 深度查询据点符(.)进行查询

4.2.1万能的点获取值

views.py视图函数中写法

from django.shortcuts import render
def home(request):
    import datetime
    current_time = datetime.datetime.now()
    name = '小白'
    num = 101
    d1 = {'xx':'oo','xx2':'oo2','xx3':[11,22,33]}
    d2 = ['11','22','33']
    d3 = []
    l1 = ['李业','陈硕','王洋','海狗']
    class Person:
        n = '类的属性'
        def p(self):
            return '类p的返回值'
    obj = Person()
    return render(request,'home.html',{'name':name,'d1':d1})

HTML页面写法

注意字典 列表 和对象中方法

<h2>{{ name }}</h2>
<h2>{{ d1.items }}</h2>items keys vlues
<h2>我是"{{ l1.1 }}"</h2>
<h2>{{ num }}</h2>
<h2>{{ obj.p }}</h2>  #如果调用的方法需要传参,sorry用不了

4.3过滤器(内置)

过滤器的语法: {{ value|filter_name:参数 }}

使用管道符"|"来应用过滤器。

注意事项:

  1. 过滤器支持“链式”操作。即一个过滤器的输出作为另一个过滤器的输入。

  2. 过滤器可以接受参数,例如:{{ sss|truncatewords:30 }},这将显示sss的前30个词。

  3. 过滤器参数包含空格的话,必须用引号包裹起来。比如使用逗号和空格去连接一个列表中的元素,如:{{ list|join:‘, ‘ }}

  4. ‘|‘左右没有空格没有空格没有空格

参考博客:https://www.cnblogs.com/clschao/articles/10414811.html
default 如果一个变量是false或者为空,使用给定的默认值。 否则,使用变量的值。
{{ value|default:"nothing"}}
如果value没有传值或者值为空的话就显示nothing

length返回值的长度,作用于字符串和列表。
{{ value|length }}
返回value的长度,如 value=['a', 'b', 'c', 'd']的话,就显示4.

filesizeformat将值格式化为一个 “人类可读的” 文件尺寸 (例如 '13 KB', '4.1 MB', '102 bytes', 等等)。
{{ value|filesizeformat }}
如果 value 是 123456789,输出将会是 117.7 MB。

slice
切片,如果 value="hello world",还有其他可切片的数据类型
{{value|slice:"2:-1"}}

date格式化,
value=datetime.datetime.now()
{{ value|date:"Y-m-d H:i:s"}}
关于时间日期的可用的参数(除了Y,m,d等等)还有很多,有兴趣的可以去查查看看。

safe
{{ value|safe}}
如果value = "<a href='#'>点我</a>"   那么页面显示的是a标签

truncatechars如果字符串字符多于指定的字符数量,那么会被截断。截断的字符串将以可翻译的省略号序列(“...”)结尾。
{{ value|truncatechars:9}} #注意:最后那三个省略号也是9个字符里面的,也就是这个9截断出来的是6个字符+3个省略号,有人会说,怎么展开啊,配合前端的点击事件就行啦

truncatewords在一定数量的字后截断字符串,是截多少个单词。
例如:‘hello girl hi baby yue ma’,
{{ value|truncatewords:3}}  #上面例子得到的结果是 'hello girl h1...'

cut移除value中所有的与给出的变量相同的字符串

{{ value|cut:' ' }}
    如果value为'i love you',那么将输出'iloveyou'.

join使用字符串连接列表,{{ list|join:', ' }},就像Python的str.join(list)
 

4.4标签Tags

标签看起来像是这样的: {% tag %}。标签比变量更加复杂:

格式 {% tag %}标签 内容 ... {% endtag %}

4.4.1for标签

{% 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            当前循环的索引值(从1开始),forloop是循环器,通过点来使用功能
forloop.counter0           当前循环的索引值(从0开始)
forloop.revcounter         当前循环的倒序索引值(从1开始)
forloop.revcounter0        当前循环的倒序索引值(从0开始)
forloop.first              当前循环是不是第一次循环(布尔值)
forloop.last               当前循环是不是最后一次循环(布尔值)
forloop.parentloop         本层循环的外层循环的对象,再通过上面的几个属性来显示外层循环的计数等
实列
{% for i in d2 %}
    {% for k,v in d1.items %}

        <li>{{ forloop.counter }}-- {{ forloop.parentloop.counter }} === {{ k }} -- {{ v }}</li>

    {% endfor %}

{% endfor %}

4.4.2for ... empty

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

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

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

4.4.3if 标签

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

{% if num > 100 or num < 0 %}
    <p>无效</p>  <!--不满足条件,不会生成这个标签-->
{% elif num > 80 and num < 100 %}
    <p>优秀</p>
{% else %}  <!--也是在if标签结构里面的-->
    <p>凑活吧</p>
{% endif %}

if语句支持 and 、or、==、>、<、!=、<=、>=、in、not in、is、is not判断,注意条件两边都有空格。

4.4.4with

多用于给一个复杂的变量起别名,当你需要使用一个“昂贵的”方法(比如访问数据库)很多次的时候是非常有用的

方法1
{% with total=business.employees.count %}  #注意等号两边不能有空格
    {{ total }} <!--只能在with语句体内用-->
{% endwith %}
方法2
{% with business.employees.count as total %}
    {{ total }}
{% endwith %}

4.4.5csrf_token

安全认证机制  
    我们以post方式提交表单的时候,会报错,还记得我们在settings里面的中间件配置里面把一个csrf的防御机制给注销了啊,本身不应该注销的,而是应该学会怎么使用它,并且不让自己的操作被forbiden,通过这个东西就能搞定。

    这个标签用于跨站请求伪造保护,

    在页面的form表单里面(注意是在form表单里面)任何位置写上{% csrf_token %},这个东西模板渲染的时候替换成了<input type="hidden" name="csrfmiddlewaretoken" value="8J4z1wiUEXt0gJSN59dLMnktrXFW0hv7m4d40Mtl37D7vJZfrxLir9L3jSTDjtG8">,隐藏的,这个标签的值是个随机字符串,提交的时候,这个东西也被提交了,首先这个东西是我们后端渲染的时候给页面加上的,那么当你通过我给你的form表单提交数据的时候,你带着这个内容我就认识你,不带着,我就禁止你,因为后台我们django也存着这个东西,和你这个值相同的一个值,可以做对应验证是不是我给你的token,存储这个值的东西我们后面再学,你先知道一下就行了,就像一个我们后台给这个用户的一个通行证,如果你用户没有按照我给你的这个正常的页面来post提交表单数据,或者说你没有先去请求我这个登陆页面,而是直接模拟请求来提交数据,那么我就能知道,你这个请求是非法的,反爬虫或者恶意攻击我的网站,以后将中间件的时候我们在细说这个东西,但是现在你要明白怎么回事,明白为什么django会加这一套防御。

处理反扒
先get请求拿到<input type="hidden" name="csrfmiddlewaretoken" value="8J4z1wiUEXt0gJSN59dLMnktrXFW0hv7m4d40Mtl37D7vJZfrxLir9L3jSTDjtG8">,
name与values 在去请求

注意事项

  1. Django的模板语言不支持连续判断,即不支持以下写法:
{% if a > b > c %}
...
{% endif %}

4.5模板继承

4.5.1为什么要模板基础?

在写html页面中 发现有很多页面有雷同的样式 为了不必重复造轮子

Web框架需要一种很便利的方法用于动态生成HTML页面。 最常见的做法是使用模板。

模板包含所需HTML页面的静态部分,以及一些特殊的模版语法,用于将动态内容插入静态部分。

模板的设计实现了业务逻辑view与显示内容template的分离,一个视图可以使用任意一个模板,一个模板可以供多个视图使用。

4.5.2模板继承怎么实现?

1. 创建一个xx.html页面(作为母版,其他页面来继承它使用)
2. 在母版中定义block块(可以定义多个,整个页面任意位置)
    {% block content %}  <!-- 预留的钩子,共其他需要继承它的html,自定义自己的内容 -->
    {% endblock %}
3 其他页面继承写法
    {% extends 'base.html' %}  必须放在页面开头
4 页面中写和母版中名字相同的block块,从而来显示自定义的内容
    {% block content %}  <!-- 预留的钩子,共其他需要继承它的html,自定义自己的内容 -->
        {{ block.super }}  #这是显示继承的母版中的content这个快中的内容
        这是xx1
    {% endblock %}
以下是具体运行代码

4.5.2.1创建一个母模板

在templates文件夹 中创建一个muban.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>模板</title>
    <style>
        {% block css %}
        #mub{
            width: 100%;
            height: 50px;
            background-color: cornflowerblue;
        }
        {% endblock %}{#预留的钩子,共其他需要继承它的html,自定义自己的内容#}
    </style>
</head>
<body>
<div id="mub">我是模板</div>

{% block content %}  <!-- 预留的钩子,共其他需要继承它的html,自定义自己的内容 -->
    <h1>我是模板h1</h1>
{% endblock %}
{% block cs2 %}  <!-- 预留的钩子,共其他需要继承它的html,自定义自己的内容 -->
    <h1>我是测试2</h1>
{% endblock %}
</body>
</html>

4.5.2.2其他页面继承写法

在templates文件夹 中创建一个home.html 继承于muban.html

{% extends 'muban.html' %}

{% block css %}
    #mub{
        width: 100%;
        height: 50px;
        background-color: red;
    }
    #s6{
        width: 50%;
        height: 50px;
        background-color: red;
        float: right;
    }
    {% endblock %}




{% block content %}  <!-- 预留的钩子,共其他需要继承它的html,自定义自己的内容 -->
<h1>我改变了模板的内容</h1>
<div id="s6">我来测试</div>
{% endblock %}


{% block cs2 %}  <!-- 预留的钩子,共其他需要继承它的html,自定义自己的内容 -->
    {{ block.super }}
    我在测试2下面
{% endblock %}

4.6组件

组件就是类似于python中的模块 什么时候用 什么时候导入 比如常见的导航条,页尾信息等组件 我们一般 保存在单独的文件中,

1 创建html页面,里面写上自己封装的组件内容,xx.html
2 新的html页面使用这个组件
    {% include 'xx.html' %}
以下是代码

4.6.1创建组件

在templates文件夹 中创建一个组件 title.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
        .nav{
            background-color: pink;
            height: 40px;

        }

    </style>
</head>
<body>

<div class="nav">
    <span>个人中心</span>
    <span>首页</span>
    <span>注册</span>
    <span>登录</span>

</div>


</body>

</html>

4.6.2引用组件

在templates文件夹 中创建一个home.html 引用组件 title.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>

</head>
<body>
{% include 'title.html' %}

<h1>这是新项目首页</h1>

</body>
</html>

4.7自定义标签和过滤器

4.7.1为什么要有自定义标签和过滤器?

因为在现实编程中可能内置的标签过滤器 不可以满足我们的需求 所有需要我们自己来创建

4.7.2创建自定义标签和过滤器的流程

1 在应用下创建一个叫做templatetags的文件夹(名称不能改),在里面创建一个py文件,例如xx.py

2 在xx.py文件中引用django提供的template类,写法
    from django import template
    register = template.Library() #register变量名称不能改
    
    定义过滤器
        @register.filter   参数至多两个
        def xx(v1,v2):
            return xxx
    使用:
        {% load xx %} xx是py文件
        {{ name|xx:'oo' }}
    
    # 自定义标签 没有参数个数限制
    from django import template
    register = template.Library() #register变量名称不能改

    @register.filter   #参数至多两个
    def guolv(v1,v2):
        """
        :param v1: 变量的值 管道前面的
        :param v2: 传的参数 管道后面的,如果不需要传参,就不要添加这个参数
        :return: 
        """
        return v1+v2


下面是执行的代码

4.7.2.1在应用文件夹下 创建templatetags文件夹并在里面创建一个xx.文件

from django import template
register = template.Library() #register变量名称不能改

@register.filter   #参数至多两个
def guolv(v1,v2):
    """
    :param v1: 变量的值 管道前面的
    :param v2: 传的参数 管道后面的,如果不需要传参,就不要添加这个参数
    :return: 
    """
    return v1+v2

4.7.2.2视图views中代码

from django.shortcuts import render,HttpResponse
name='测试+'
def home(request):
    return render(request,'home.html',{'name':name})

4.7.2.3创建要引用自定义过滤器的html页面

{% load xx %}{#xx是templatetags文件夹下的xx.py文件#}
<!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport"
          content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>
<body>
{{ name|guolv:'要传给n2的参数' }}

</body>
</html>

4.7.3 inclusion_tag

多用于返回html代码片段

原理先运行nue.html 调用xx.py 中res函数

res函数将返回值给@register.inclusion_tag对应的页面(‘result.html‘) 模板渲染后 以组件的形式给原来的nue.htm

nue.htm

{% load xx %}
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>

{% res a %}#a是参数

</body>

</html>

result.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>

<ul>
    {% for i in li %}

        <li>{{ i }}</li>
    {% endfor %}
</ul>
</body>

</html>

xx.py

# inclusion_tag 返回html片段的标签
@register.inclusion_tag('result.html')
def res(n1): #n1 : ['aa','bb','cc']
    return {'li':n1 }

4.8静态文件相关

4.8.1静态文件配置

js、css、img等都叫做静态文件,那么关于django中静态文件的配置,我们就需要在settings配置文件里面写上这写内容:

目录:别名也是一种安全机制,浏览器上通过调试台你能够看到的是别名的名字,这样别人就不能知道你静态文件夹的名字了,不然别人就能通过这个文件夹路径进行攻击。

1 项目目录下创建一个文件夹,例如名为static_file,将所有静态文件放到这个文件夹中
2 settings 配置文件中进行下面的配置
    # 静态文件相关配置
    STATIC_URL = '/abc/'  #静态文件路径别名

    STATICFILES_DIRS = [
        os.path.join(BASE_DIR, 'jingtaiwenjianjia'),
    ]
    
    
{% load static %}
3 引入<link rel="stylesheet" href="/abc/css/index.css">

4.8.1.1项目目录下创建一个文件夹,例如名为static_file,将所有静态文件放到这个文件夹中

技术图片

4.8.1.2 找到settings 配置文件中进行下面的配置

STATIC_URL = '/abc/'  #静态文件路径别名 可以随便改
   #注意第2个参数一定对应创建的文件夹名 别名可以随便改
   STATICFILES_DIRS = [
        os.path.join(BASE_DIR, 'static_file'),
   ]

4.8.1.3引入的配置文件的html页面内容

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <link rel="stylesheet" href="/abc/css/index.css">
    <link rel="stylesheet" href="/abc/plugins/bootstrap-3.3.7-dist/css/bootstrap.min.css">
</head>
<body>

<input type="text" class="form-control">
<h1>红浪漫spa会所</h1>
<img src="/abc/img/timg.jpg" alt="">
<a href="{% url 'home' %}">首页</a>

技师:
<ul>
    <li>小白</li>
    <li>小黑</li>
</ul>

</body>
</html>

4.8.2url别名和反向解析

我们给url 起一个别名· 以后不管url怎么改 都可以实现原来的网址 就不会写死了

rurl文件写法
    url(r'^index2/', views.index,name='cs'),
反向解析
    后端views: from django.urls import reverse 可以实现反向解析
         reverse('别名')  例如:reverse('cs') 反向解析为别名对应的地址 /index2/
         带参数的反向解析: reverse( index' ,args=(10,))--- /index2/10/
    html: {% url '别名' %} -- 例如:{% url 'cs' %} -- /index2/
下面是代码

rurl文件写法

from django.conf.urls import url
from django.contrib import admin
from app01 import views
urlpatterns = [
    url(r'^cs/', views.home,name='cs'),
    url(r'^cs1/', views.cs1,name='cs1'),
]

后端views.py

用于重定向 redirect
我们利用别名 以后不管 别名cs1 对应的网址这么变  我们通过反解析 ,都可以找到他,写活了他 
from django.shortcuts import render,HttpResponse,redirect
from django.urls import reverse

def home(request):
    return redirect(reverse('cs1'))
def cs1(request):
    return HttpResponse('测试')

4.8.3url命名空间

在路由分发中可能会错乱为了 避免

from django.conf.urls import url,include
from django.contrib import admin
urlpatterns = [
    # url(r'^admin/', admin.site.urls),
    url(r'^app01/', include('app01.urls',namespace='app01')),#app01/home/
    url(r'^app02/', include('app02.urls',namespace='app02')),
    
]


使用:
    后端:reverse('命名空间名称:别名') -- reverse('app01:home') 
    hmtl:{% url '命名空间名称:别名' %}  -- {% url 'app01:home' %}

5 orm单表操作

orm语句 -- sql -- 调用pymysql客户端发送sql -- mysql服务端接收到指令并执行

5.1ORM简介

  • MVC或者MVC框架中包括一个重要的部分,就是ORM,它实现了数据模型与数据库的解耦,即数据模型的设计不需要依赖于特定的数据库,通过简单的配置就可以轻松更换数据库,这极大的减轻了开发人员的工作量,不需要面对因数据库变更而导致的无效劳动
  • ORM是“对象-关系-映射”的简称。(Object Relational Mapping,简称ORM)(将来会学一个sqlalchemy,是和他很像的,但是django的orm没有独立出来让别人去使用,虽然功能比sqlalchemy更强大,但是别人用不了)
  • 类对象--->sql--->pymysql--->mysql服务端--->磁盘,orm其实就是将类对象的语法翻译成sql语句的一个引擎,明白orm是什么了,剩下的就是怎么使用orm,怎么来写类对象关系语句。

5.2单表操作

5.2.1创建表

注意创建表前 必须先手动在数据库 中创建一个库 并配好setting中配置

第一步在应用文件夹下 models.py文件中创建一个类
字段与参数 详见5.2.1

class Csbiao(models.Model):#Csbiao创建的表名
    id=models.AutoField(primary_key=True)
    name=models.CharField(max_length=10)
    birthday=models.DateField()
    checked = models.BooleanField()
4 执行数据库同步指令,添加字段的时候别忘了,该字段不能为空,所有要么给默认值,要么设置它允许为空null=True


在 Terminal中执行
python manage.py makemigrations  #生成记录,每次修改了models里面的内容或者添加了新的app,新的app里面写了models里面的内容,都要执行这两条
python manage.py migrate         #执行上面这个语句的记录来创建表,生成的表名字前面会自带应用的名字,例如:你的book表在mysql里面叫做app01_book表
5.2.1 settings配置
settings配置文件中
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',#固定的
        'NAME': 'cs',#cs是数据库中的库
        'USER':'root',#账号
        'PASSWORD':'',#密码
        'HOST':'127.0.0.1',#ip地址
        'PORT':3306,#端口号
    }
}



2 项目文件夹下的init文件中写上下面内容,用pymysql替换mysqldb
import pymysql
pymysql.install_as_MySQLdb()


 settings配置文件中将USE_TZ的值改为False
    # USE_TZ = True
    USE_TZ = False  # 告诉mysql存储时间时按照当地时间来寸,不要用utc时间
使用pycharm的数据库客户端的时候,时区问题要注意
5.2.1 更多字段和参数
<1> CharField
        字符串字段, 用于较短的字符串.
        CharField 要求必须有一个参数 maxlength, 用于从数据库层和Django校验层限制该字段所允许的最大字符数.
 
<2> IntegerField
       #用于保存一个整数.
 
<3> DecimalField
        一个浮点数. 必须 提供两个参数:
         
        参数    描述
        max_digits    总位数(不包括小数点和符号)
        decimal_places    小数位数
                举例来说, 要保存最大值为 999 (小数点后保存2位),你要这样定义字段:
                 
                models.DecimalField(..., max_digits=5, decimal_places=2)
                要保存最大值一百万(小数点后保存10位)的话,你要这样定义:
                 
                models.DecimalField(..., max_digits=17, decimal_places=10) #max_digits大于等于17就能存储百万以上的数了
                admin 用一个文本框(<input type="text">)表示该字段保存的数据.
 
<4> AutoField
        一个 IntegerField, 添加记录时它会自动增长. 你通常不需要直接使用这个字段;
        自定义一个主键:my_id=models.AutoField(primary_key=True)
        如果你不指定主键的话,系统会自动添加一个主键字段到你的 model.
 
<5> BooleanField    bool字段
        A true/false field. admin 用 checkbox 来表示此类字段.
 
<6> TextField
        一个容量很大的文本字段.
        admin 用一个 <textarea> (文本区域)表示该字段数据.(一个多行编辑框).
 
<7> EmailField
        一个带有检查Email合法性的 CharField,不接受 maxlength 参数.
 
<8> DateField
        一个日期字段. 共有下列额外的可选参数:
        Argument    描述
        auto_now    当对象被保存时(更新或者添加都行),自动将该字段的值设置为当前时间.通常用于表示 "last-modified" 时间戳.
        auto_now_add    当对象首次被创建时,自动将该字段的值设置为当前时间.通常用于表示对象创建时间.
        (仅仅在admin中有意义...)
 
<9> DateTimeField
         一个日期时间字段. 类似 DateField 支持同样的附加选项.
 
<10> ImageField 图片·
        类似 FileField, 不过要校验上传对象是否是一个合法图片.#它有两个可选参数:height_field和width_field,
        如果提供这两个参数,则图片将按提供的高度和宽度规格保存.    
        
<11> FileField  文件
     一个文件上传字段.
     要求一个必须有的参数: upload_to, 一个用于保存上载文件的本地文件系统路径. 这个路径必须包含 strftime #formatting,
     该格式将被上载文件的 date/time
     替换(so that uploaded files don't fill up the given directory).
     admin 用一个<input type="file">部件表示该字段保存的数据(一个文件上传部件) .
 
     注意:在一个 model 中使用 FileField 或 ImageField 需要以下步骤:
            (1)在你的 settings 文件中, 定义一个完整路径给 MEDIA_ROOT 以便让 Django在此处保存上传文件.
            (出于性能考虑,这些文件并不保存到数据库.) 定义MEDIA_URL 作为该目录的公共 URL. 要确保该目录对
             WEB服务器用户帐号是可写的.
            (2) 在你的 model 中添加 FileField 或 ImageField, 并确保定义了 upload_to 选项,以告诉 Django
             使用 MEDIA_ROOT 的哪个子目录保存上传文件.你的数据库中要保存的只是文件的路径(相对于 MEDIA_ROOT).
             出于习惯你一定很想使用 Django 提供的 get_<#fieldname>_url 函数.举例来说,如果你的 ImageField
             叫作 mug_shot, 你就可以在模板中以 {{ object.#get_mug_shot_url }} 这样的方式得到图像的绝对路径.
 
<12> URLField
      用于保存 URL. 若 verify_exists 参数为 True (默认), 给定的 URL 会预先检查是否存在( 即URL是否被有效装入且
      没有返回404响应).
      admin 用一个 <input type="text"> 文本框表示该字段保存的数据(一个单行编辑框)
 
<13> NullBooleanField
       类似 BooleanField, 不过允许 NULL 作为其中一个选项. 推荐使用这个字段而不要用 BooleanField 加 null=True 选项
       admin 用一个选择框 <select> (三个可选择的值: "Unknown", "Yes" 和 "No" ) 来表示这种字段数据.
 
<14> SlugField
       "Slug" 是一个报纸术语. slug 是某个东西的小小标记(短签), 只包含字母,数字,下划线和连字符.#它们通常用于URLs
       若你使用 Django 开发版本,你可以指定 maxlength. 若 maxlength 未指定, Django 会使用默认长度: 50.  #在
       以前的 Django 版本,没有任何办法改变50 这个长度.
       这暗示了 db_index=True.
       它接受一个额外的参数: prepopulate_from, which is a list of fields from which to auto-#populate
       the slug, via JavaScript,in the object's admin form: models.SlugField
       (prepopulate_from=("pre_name", "name"))prepopulate_from 不接受 DateTimeFields.
 
<13> XMLField
        一个校验值是否为合法XML的 TextField,必须提供参数: schema_path, 它是一个用来校验文本的 RelaxNG schema #的文件系统路径.
 
<14> FilePathField
        可选项目为某个特定目录下的文件名. 支持三个特殊的参数, 其中第一个是必须提供的.
        参数    描述
        path    必需参数. 一个目录的绝对文件系统路径. FilePathField 据此得到可选项目.
        Example: "/home/images".
        match    可选参数. 一个正则表达式, 作为一个字符串, FilePathField 将使用它过滤文件名. 
        注意这个正则表达式只会应用到 base filename 而不是
        路径全名. Example: "foo.*\.txt^", 将匹配文件 foo23.txt 却不匹配 bar.txt 或 foo23.gif.
        recursive可选参数.要么 True 要么 False. 默认值是 False. 是否包括 path 下面的全部子目录.
        这三个参数可以同时使用.
        match 仅应用于 base filename, 而不是路径全名. 那么,这个例子:
        FilePathField(path="/home/images", match="foo.*", recursive=True)
        ...会匹配 /home/images/foo.gif 而不匹配 /home/images/foo/bar.gif
 
<15> IPAddressField
        一个字符串形式的 IP 地址, (i.e. "24.124.1.30").
<16> CommaSeparatedIntegerField
        用于存放逗号分隔的整数值. 类似 CharField, 必须要有maxlength参数.
 
 
 

更多参数

1)null
 
如果为True,Django 将用NULL 来在数据库中存储空值。 默认值是 False.
 
(1)blank
 
如果为True,该字段允许不填。默认为False。
要注意,这与 null 不同。null纯粹是数据库范畴的,而 blank 是数据验证范畴的。
如果一个字段的blank=True,表单的验证将允许该字段是空值。如果字段的blank=False,该字段就是必填的。
 
(2)default
 
字段的默认值。可以是一个值或者可调用对象。如果可调用 ,每有新对象被创建它都会被调用,如果你的字段没有设置可以为空,那么将来如果我们后添加一个字段,这个字段就要给一个default值
 
(3)primary_key
 
如果为True,那么这个字段就是模型的主键。如果你没有指定任何一个字段的primary_key=True,
Django 就会自动添加一个IntegerField字段做为主键,所以除非你想覆盖默认的主键行为,
否则没必要设置任何一个字段的primary_key=True。
 
(4)unique
 
如果该值设置为 True, 这个数据字段的值在整张表中必须是唯一的
 
(5)choices
由二元组组成的一个可迭代对象(例如,列表或元组),用来给字段提供选择项。 如果设置了choices ,默认的表单将是一个选择框而不是标准的文本框,<br>而且这个选择框的选项就是choices 中的选项。
(6)db_index
  如果db_index=True 则代表着为此字段设置数据库索引。


DatetimeField、DateField、TimeField这个三个时间字段,都可以设置如下属性。

(7)auto_now_add
    配置auto_now_add=True,创建数据记录的时候会把当前时间添加到数据库。

(8)auto_now
    配置上auto_now=True,每次更新数据记录的时候会更新该字段,标识这条记录最后一次的修改时间。
5.2.1自定义字段(了解)

5.2.2添加表纪录

第一步views表引入app01文件夹下的models.py文件from app01 import models

方式1:
new_obj=models.Csbiao(#Csbiao类名也是表名
        name='cs',
        birthday='2019-09-27',
        checked=1,
    )
new_obj.save() 
方式2:
    ret = models.Csbiao.objects.create(
        name='cs111',
        birthday='2019-09-27',
        checked=1,
    )
    # ret 是创建的新的记录的model对象(重点)
    
    print(ret)  #UserInfo object  卫贺
    print(ret.name)  #UserInfo object
    print(ret.bday)  #UserInfo object

5.2.2.1 时间问题
models.UserInfo.objects.create(
        name='杨泽涛2',
        bday=current_date,
        # now=current_date,  直接插入时间没有时区问题
        checked=0
    )
    但是如果让这个字段自动来插入时间,就会有时区的问题,auto_now_add创建记录时自动添加当前创建记录时的时间,存在时区问题
now = models.DateTimeField(auto_now_add=True,null=True)

解决方法:
    settings配置文件中将USE_TZ的值改为False
    # USE_TZ = True
    USE_TZ = False  # 告诉mysql存储时间时按照当地时间来寸,不要用utc时间
使用pycharm的数据库客户端的时候,时区问题要注意

5.2.3查询表纪录

<1> all():                  查询所有结果,结果是queryset类型
  查询所有的数据  .all方法 返回的是queryset集合
    all_objs = models.Student.objects.all()  # 类似于列表  --  queryset集合
    # for i in all_objs:
    #     print(i.name)
    print(all_objs)
    
<2> filter(**kwargs):       它包含了与所给筛选条件相匹配的对象,结果也是queryset类型 Book.objects.filter(title='linux',price=100) #里面的多个条件用逗号分开,并且这几个条件必须都成立,是and的关系,or关系的我们后面再学,直接在这里写是搞不定or的
    models.Student.objects.filter(id=7,name='大壮哥哥',age=78).update(
        name='大壮禅师',
        age=78
    )
    #打散形式传参
    models.Student.objects.filter(**{'id':7,'name':'大壮禅师'}).update(age=100)
    models.Student.objects.all().filter(id=7)  queryset类型可以调用fitler在过滤
  

<3> get(**kwargs):          返回与所给筛选条件相匹配的对象,不是queryset类型,是行记录对象,返回结果有且只有一个,
                            如果符合筛选条件的对象超过一个或者没有都会抛出错误。捕获异常try。  Book.objects.get(id=1)
  
<4> exclude(**kwargs):      排除的意思,它包含了与所给筛选条件不匹配的对象,没有不等于的操作昂,用这个exclude,返回值是queryset类型 Book.objects.exclude(id=6),返回id不等于6的所有的对象,或者在queryset基础上调用,Book.objects.all().exclude(id=6)
    exclude(**kwargs): 排除,objects控制器和queryset集合都可以调用,返回结果是queryset类型
    query = models.Student.objects.exclude(id=1)
    print(query)
    query = models.Student.objects.filter(age=38).exclude(id=6)
    print(query)
                 
<5> order_by(*field): 排序      queryset类型的数据来调用,对查询结果排序,默认是按照id来升序排列的,返回值还是queryset类型
                  models.Book.objects.all().order_by('price','id') #直接写price,默认是按照price升序排列,按照字段降序排列,就写个负号就行了order_by('-cs'),order_by('price','id')是多条件排序,按照price进行升序,price相同的数据,按照id进行升序
        
        
<6> reverse():              queryset类型的数据来调用,对查询结果反向排序,返回值还是queryset类型
            # 只可以排序之后反转
            # query = models.Student.objects.all().order_by('id').reverse()
            # print(query)

<7> count():                queryset类型的数据来调用,返回数据库中匹配查询(QuerySet)的对象数量。
  
<8> first():                queryset类型的数据来调用,返回第一条记录 Book值    
  
<9> last():                queryset类型的数据来调用,返回最后一条记录,结果为model对象类型
  
<10> exists():              queryset类型的数据来调用,如果QuerySet包含数据,就返回True,否则返回False
                   空的queryset类型数据也有布尔值True和False,但是一般不用它来判断数据库里面是不是有数据,如果有大量的数据,你用它来判断,那么就需要查询出所有的数据,效率太差了,用count或者exits
                 例:all_books = models.Book.objects.all().exists() #翻译成的sql是SELECT (1) AS `a` FROM `app01_book` LIMIT 1,就是通过limit 1,取一条来看看是不是有数据

<11> values(*field):        用的比较多,queryset类型的数据来调用,返回一个ValueQuerySet——一个特殊的QuerySet,运行后得到的并不是一系列
                            model的实例化对象,而是一个可迭代的字典序列,只要是返回的queryset类型,就可以继续链式调用queryset类型的其他的查找方法,其他方法也是一样的。 里面可以加子段显示
        
<12> values_list(*field):   它与values()非常相似,它返回的是一个元组序列,values返回的是一个字典序列 里面可以加子段显示
 
<13> distinct():            values和values_list得到的queryset类型的数据来调用,从返回结果中剔除重复纪录 去重,结果还是queryset 里面不可以传参 显示nanme等等可以用来去重
    query = models.Student.objects.all().values('age').distinct()
    print(query)
    
5.2.3.2基于双下划线的模糊查询 
Book.objects.filter(price__in=[100,200,300]) #price值等于这三个里面的任意一个的对象
Book.objects.filter(price__gt=100)  #大于,大于等于是price__gte=100,别写price>100,这种参数不支持
Book.objects.filter(price__lt=100) 小于
Book.objects.filter(price__range=[100,200])  #sql的between and,大于等于100,小于等于200
Book.objects.filter(title__contains="python")  #title值中包含python的
Book.objects.filter(title__icontains="python") #不区分大小写
Book.objects.filter(title__startswith="py") #以什么开头,istartswith  不区分大小写
Book.objects.filter(pub_date__year=2012) date类型

# all_books = models.Book.objects.filter(pub_date__year=2012) #找2012年的所有书籍
    # all_books = models.Book.objects.filter(pub_date__year__gt=2012)#找大于2012年的所有书籍
    all_books = models.Book.objects.filter(pub_date__year=2019,pub_date__month=2)#找2019年月份的所有书籍,如果明明有结果,你却查不出结果,是因为mysql数据库的时区和咱们django的时区不同导致的,了解一下就行了,你需要做的就是将django中的settings配置文件里面的USE_TZ = True改为False,就可以查到结果了,以后这个值就改为False,而且就是因为咱们用的mysql数据库才会有这个问题,其他数据库没有这个问题。

5.2.4删除表纪录

简单查询:filter()  -- 结果是queryset类型的数据里面是一个个的model对象,类似于列表
    models.UserInfo.objects.filter(id=7).delete()  #queryset对象调用
    models.UserInfo.objects.filter(id=7)[0].delete()  #model对象调用

5.2.5修改表纪录

方式1:update
     models.UserInfo.objects.filter(id=2).update(
         name='篮子文',
         checked = 0,
    
     )
     #错误示例,model对象不能调用update方法
     models.UserInfo.objects.filter(id=2)[0].update(
         name='加篮子+2',
         # checked = 0,
     )
方式2 
    ret = models.UserInfo.objects.filter(id=2)[0]
    ret.name = '加篮子+2'
    ret.checked = 1
    ret.save()
    

更新时的auto_now参数
    # 更新记录时,自动更新时间,创建新纪录时也会帮你自动添加创建时的时间,但是在更新时只有使用save方法的方式2的形式更新才能自动更新时间,有缺陷,放弃
    now2 = models.DateTimeField(auto_now=True,null=True)

python之Django

标签:完整   建表   全路径   失败   函数返回   翻译   集合   字符   链式   

原文地址:https://www.cnblogs.com/saoqiang/p/11600980.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!