Django基础及实战

day52

今日内容

内容规格

Python的基础

面向对象

网络

并发

数据库

前端

今日内容

  1. web框架 原理
  2. Django的下载安装使用

百度 socket服务端

  1. socket服务端启动
    2. 绑定ip和端口
    3. 监听等待连接
  2. 接受数据
  3. 返回数据
  4. 断开连接

浏览器 socket客户端

4. socket客户端启动
  1. 连接(ip和端口)
  2. 发送数据
  3. 接受数据
  4. 断开连接

https://www.cnblogs.com/maple-shaw/articles/9060408.html

HTTP协议:

http是请求和应答的标准

请求方式:8种 主要是GET POST

状态码 1xx 2xx 3xx 4xx 5xx

请求格式:

​ ‘请求方式 路径 协议版本

​ 请求头: 值

​ 请求头: 值

​ 请求数据’

响应格式:

​ '协议版本 状态码 状态描述

​ 请求头: 值

​ 请求头: 值

​ 响应数据'

web框架的实现的功能:

  1. socket收发消息
  2. 根据不同的路径返回不同的内容
  3. 返回HTML页面
  4. 返回动态的页面 (模板的渲染 字符串的替换)

web框架

Django 2 3 4

flask 2 3

tornado 1 2 3 4

Django 大而全

flask tornado 轻量级的框架

Django

下载:

  1. 命令行

pip install -i django==1.11.25 -i https://pypi.tuna.tsinghua.edu.cn/simple

  1. pycharm

    在项目的解释器中找对应的Django版本下载

创建项目

  1. 命令行

    django-admin 项目名

  2. pycharm

    file ——》 new project ——》 填写项目名称 ——》 选择解释器 ——》 create

启动项目

  1. 命令行

    python manage.py runserver # 127.0.0.1:8000

    python manage.py runserver 80 # 127.0.0.1:80

    python manage.py runserver 0.0.0.0:80 # 0.0.0.0:80

    1. pycharm

简单使用

  1. urls.py中写路径和函数的对应关系

    urlpatterns = [
        url(r'^index/', index),
    ]
    
  2. 写函数

    from django.shortcuts import HttpResponse ,render
    def index(request):
        # 逻辑
        # return HttpResponse('欢迎进入day5项目')   # 返回字符串
        return render(request,'index.html')  # 返回一个HTML页面    页面写在templates文件夹中
    

作业:

​ 用bootstrap写登录页面,使用Django返回给浏览器

day53

内容回顾

HTTP

规定请求和响应的格式。

请求方法

8种 GET POST ( PUT DELETE HEAD OPTIONS TRACE CONNECT )

状态码

1xx 请求已接受,进一步进行处理

2xx 请求已经接受,也正常处理

3xx 重定向

4xx 请求的错误 403 404

5xx 服务器的错误

URL

https://www.sogou.com/web?query=苍老师&_asf=www.sogou.com

协议 : https

域名: www.sogou.com ip

端口: https (:443) http (:80)

路径: /web

查询的参数: ?后面 k1=v1&k2=v2

请求和响应的格式

请求(浏览器给服务端发的消息) request

	‘请求方式 路径 HTTP/1.1

	  k1:v1

	  k2:v2

	  请求数据(请求体)’

响应(服务器返回给浏览器的消息) response

	'HTTP/1.1 状态码 状态描述

	  k1:v1

	  k2:v2

	  响应数据(响应体)’'

请求和响应的步骤

  1. 在浏览器的地址栏种输入URL地址,回车,发个一个GET请求;
  2. Django接受到请求,根据URL的路径找到对应的函数,执行函数拿到结果
  3. Django将结果封装成http响应的报文返回浏览器
  4. 浏览器接受响应,断开连接,解析数据。

框架的功能

  1. socket收发消息
  2. 根据不同路径返回不同的结果(返回HTML页面)
  3. 返回动态的页面( 模板的渲染 字符串的替换 )

Django部分

  1. 下载安装

    命令行:

    pip install django==1.11.25  -i  源
    

    pycharm:

    1. 创建项目

    命令行:

    django-admin startproject 项目名
    

    pycharm

    区别: pycharm创建时帮忙创建一个templates的文件夹,配置了模板的路径

  2. 启动项目

    命令行:

     cd 项目的根目录下
     
     python  manage.py runserver    #  127.0.0.1:8000
     
     python  manage.py runserver 80    #  127.0.0.1:80
     
     python  manage.py runserver 0.0.0.0:80    #  0.0.0.0:80
    

    pycharm:

     点绿三角   相关的配置
    
  3. 使用:

    1. 设计URL 和 函数的对应关系  urls.py
        urlpatterns = [
           url(r'^index/', index),
    	]
    2. 写函数
    	from django.shortcuts import HttpResponse,render  
    	def 函数名(request):
    		# 逻辑 
    		# 查询数据库 插入
    		# 返回信息给浏览器
    		return HttpResponse('字符串')
    		return render(request,‘html文件名’)
    
    

今日内容

1.静态文件的配置

settings:

STATIC_URL = '/static/'   # 静态文件的别名  以它做开头

STATICFILES_DIRS = [   #  静态文件存放的具体路径
    os.path.join(BASE_DIR,'static',)
]

http://www.jq22.com

2.登录示例

form表单提交数据

  1. action="" 向当前的地址进行提交 method="post" 请求方式
  2. input需要有name属性 value值
  3. button按钮或者input 类型是submit

在settings中注释一行代码,注释后可以提交post请求

MIDDLEWARE
'django.middleware.csrf.CsrfViewMiddleware' 
request.method  请求方式 GET POST
request.POST    POST请求的数据  {} 
redirect(‘要重定向的地址’)   重定向 

3.app

创建app

python manage.py startapp app名称

注册app

INSTALLED_APPS = [
  	... 
    'app01',
    'app01.apps.App01Config'    # 推荐写法
]

app文件目录

admin.py   admin管理后台  增删改查数据库
apps.py    app相关
models.py  数据库表相关
views.py   写函数(逻辑)

4.ORM

对应关系

类 ——》 表

对象 ——》 数据行(记录)

属性 ——》 字段

django要使用mysql数据库流程

  1. 创建一个mysql数据库;

  2. 在settings中配置数据库信息:

    DATABASES = {
        'default': {
            'ENGINE': 'django.db.backends.mysql',   #  引擎  数据库类型
            'NAME': 'day53',				# 数据库名称
            'HOST': '127.0.0.1',			# ip
            'PORT': 3306,					# 端口
            'USER': 'root',					# 用户名
            'PASSWORD': '123'				# 密码
        }
    }
    
  3. 告诉django使用pymysql模块连接数据库

    import pymysql   
    pymysql.install_as_MySQLdb()   # 能执行就可以
    
  4. 在app下写了model

    class User(models.Model):
        username = models.CharField(max_length=32)  # username   varchar(32)
        password = models.CharField(max_length=32)  # username   varchar(32)
    
    
  5. 执行命令 让数据有对应的结构的变化

    python manage.py makemigrations # 检查所有已经注册的app下的models.py的变化 记录成一个文件

    python manage.py migrate

ORM操作

from app01.models import User
User.objects.all()  #  查询所有的数据   QuerySet 对象列表  【  对象 】
User.objects.get(username='alexs',password='alexdsb')  
# 对象  get  只能获取数据库唯一存在的数据  有且唯一 (不存在或者多条数据就报错)

User.objects.filter(password='dsb')  # 获取满足条件的所有对象  对象列表

day54

内容回顾

  1. 下载

    命令行:

     pip install django==1.11.25  -i   源
    

    pycharm:

     file _>   settings  _>  项目  ——》 解释器  ——》  点+号  ——》  输入django  ——》 选择版本 ——》 下载
    

2.创建项目

命令行:

	django-admin  startproject  项目名

pycharm:

	file  _>   new project ——》 选择django  ——》 输入项目的路径 ——》 选择解释器  ——》 templates  还有app名称 

3.启动项目

命令行:

		切换项目的根目录下   manage.py

		python manage.py  runserver     #  127.0.0.1:8000 

		python manage.py  runserver  80   #  127.0.0.1:80

		python manage.py  runserver  0.0.0.0:80   # 0.0.0.0:80

pycharm:

		找绿三角  点击  (前面是django的项目)  

		配置ip和端口

4.settings的配置

模板文件     TEMPLATES    DIRS    [ os.path.join(BASE_DIR,'templates') ]	

静态文件

			STATIC_URL  ='/static/'    #  静态文件的别名

			STATICFILES_DIRS  = [

				os.path.join(BASE_DIR,'static')	,

				os.path.join(BASE_DIR,'static1')	

		]

数据库配置

APP

中间件

		注释一个  csrf     效果: 可以提交post请求
  1. APP

    创建APP

     python manage.py  startapp app名称   
    

    注册APP

     INSTALLED_APPS = [
     
     	'app01',
     
     	'app01.apps.App01Config'   推荐写法
    

    ]

  2. urls.py

    from app01 import views
    
    urlpatterns = [
        url(r'^admin/', admin.site.urls),
        url(r'^login/', views.login),
        url(r'^index/', views.index),
    ]
    
    
  3. views.py

    from django.shortcuts import render,HttpResponse,redirect
    
    def login(request):
    	# 逻辑
    	renturn HttpResponse('xxx')
    

    HttpResponse() 返回的字符串

    render(request,'模板的文件名') 返回HTML页面

    redirect('地址') 重定向

  4. get和post

    get 获取页面 资源

    /sssss/?k1=v1&k2=v2

    request.GET {} request.GET.get('key')

    post 提交数据

    request.POST {} request.POST.get('key')

  5. form的表单

    1. form标签的属性 action='' 提交的地址 method='post' 请求方式 novalidate 不在前端做校验
    2. input标签要有name属性 value的值
    3. 有个type=‘submit’ 的input或者button按钮
  6. django使用mysql的流程:

    1. 创建一个mysql数据库

    2. 在settings中配置数据库的信息

      EGNIGE 引擎 mysql

      NAME 数据库名称

      HOST ip

      PORT 端口 3306

      USER 用户名

      PASSWORD 密码

    3. 告诉使用pymysql替换mysqldb的模块

      写在与settings同级目录下的__init__中:

      import  pymysql
      pymysql.install_as_MySQLdb()
      
    4. 在已经注册的app下的models.py中写类(继承models.Model)

      class User(models.Model):
          username = models.CharField(max_length=32)  #  username  varchar(32)
      
    5. 执行命令

      python manage.py  makemigrations  # 记录了一个models的变更记录
      python manage.py  migrate    # 将models的变更记录同步到数据库中
      
  7. ORM

    对象关系映射

    对应关系

    类 —— 》 表

    对象 ——》 数据行(记录)

    属性 ——》 字段

    ORM能做的事情:

  8. 对数据库中表操作

  9. 对表中的数据操作

    orm具体的操作:

    from app01.models import User
    
    User.objects.all()   # 获取到所有的数据 QuerySet  [User对象]  对象列表
    User.objects.get() # 获取一个对象  只能获取唯一存在的对象   如果不存在或者是多个结果就报错
    User.objects.filter()   # 获取到所有满足条件的对象  QuerySet  [User对象]  对象列表
    

今日内容

图书管理系统

出版社 书籍 作者

出版社的管理

展示

  1. 设计URL地址

    from app01 import views
    
    urlpatterns = [
        url(r'^admin/', admin.site.urls),
        url(r'^publisher_list/', views.publisher_list),
    ]
    
  2. 写函数

    def publisher_list(request):
        # 从数据库中获取所有的出版社的信息
        all_publisher = models.Publisher.objects.all()  # 对象列表
    
        # 将数据展示到页面中
        return render(request,'publisher_list.html',{'k1':all_publisher})
    
  3. 模板语法

    {{ 变量  }}
    
    for循环
    {% for i in 变量  %}
    	循环体 {{ i }}
    {% endfor  %}
    

新增

方式一:
models.Publisher.objects.create(name=pub_name,addr=pub_addr)  # 对象
方式二:
pub_obj = models.Publisher(name=pub_name,addr=pub_addr)  # 内存中的对象 和数据库没关系
pub_obj.save()  # 插入到数据库中

删除

models.Publisher.objects.filter(pid=pid).delete()  # 对象列表 删除
models.Publisher.objects.get(pid=pid).delete()  # 对象 删除

编辑

 pub_obj.name = pub_name
 pub_obj.addr = pub_addr
 pub_obj.save()  # 将修改提交的数据库

day55

内容回顾

1.django中所有的命令

  1. 下载django

    pip install django==1.11.25 -i 源

  2. 创建django项目

    django-admin startproject 项目名

  3. 启动项目

    切换到项目目录下

    python manage.py runserver # 127.0.0.1:8000

    python manage.py runserver 80 # 127.0.0.1:80

    python manage.py runserver 0.0.0.0::80 # 0.0.0.0::80

  4. 创建app

    python manage.py startapp app名称

  5. 数据库迁移的命令

    python manage.py makemigrations # 检测已经注册app下的models变更记录

    python manage.py migrate # 将变更记录同步到数据库中

2.django的配置

  1. 静态文件

    STATIC_URL = '/static/' # 静态文件的别名

    STATICFILES_DIRS = [ # 静态文件存放的路径

    ​ os.path.join(BASE_DIR ,'static')

    ]

  2. 数据库

    ENGINE mysql

    NAME 数据库名称

    HOST ip

    PORT 端口号

    USER 用户名

    PASSWORD 密码

  3. 中间件

    注释掉 一个 csrf (可以提交POST请求)

  4. app

    INSTALLED_APPS = [

    ​ 'app名称'

    ​ ‘app名称.apps.app名称Config’

    ]

  5. 模板

    TEMPLATES DIRS =[ os.path.join(BASE_DIR ,'templates')]

3.django使用mysql数据库的流程

  1. 创建一个mysql数据库

  2. 配置数据库连接信息

    ENGINE mysql

    NAME 数据库名称

    HOST ip

    PORT 端口号

    USER 用户名

    PASSWORD 密码

  3. 告诉django使用pymysql替换Mysqldb

    在与settings同级目录下的init文件中写:

    import pymysql
    pymysql.install_as_MySQLdb()
    
  4. 在models中写类(继承models.Model)

    class Publisher(models.MOdel):
        pid = models.AutoField(primry_key=True)
        name = models.CharField(max_length=32,unique=True)
    
  5. 执行数据库迁移的命令

    python manage.py makemigrations # 检测已经注册app下的models变更记录

    python manage.py migrate # 将变更记录同步到数据库中

4.get和post的区别

发送get的方式:

  1. 地址栏中输入地址 回车
  2. a 标签
  3. from表单

?k1=v1&k2=v2 request.GET.get(key) # url携带的参数

发送post请求:

​ form表单 method ='post'

form表单

1. action=''   向当前地址进行提交  method ='post'
  1. 所有的input需要有name属性 value
  2. 需要有button或者一个type=‘submit’的input框

request.POST.get(key)

5.ORM

对象关系映射

对应关系

​ 类 ——》 表

​ 对象 ——》 数据行(记录)

​ 属性 ——》 字段

ORM操作

查询
from app01 import  models
models.Publisher.objects.all()   #  查询所有的数据    QuerySet 【对象】    对象列表
models.Publisher.objects.get(name='xxx')  #  查询有且唯一的对象  没有或者是多个就报错
models.Publisher.objects.filter(name='xxx')   # 查询所有符合条件的对象   QuerySet 【对象】    对象列表

for  i in models.Publisher.objects.all() :
	print(i)    #  Publisher object   __str__()
    print(i.name)
新增
models.Publisher.objects.create(name='xxxx',addr='xxxx')

obj = models.Publisher(name='xxxx',addr='xxxx')
obj.save()
删除
models.Publisher.objects.filter(pid=pid).delete()
models.Publisher.objects.get(pip=pid).delete()
编辑
pub_obj.name = 'xxxx'
pub_obj.addr = 'xxxx'
pub_obj.save()

6.模板语法

render(request,‘模板的文件名’,{ key:value })

{{  key }}  ——》 value的值

for循环
{% for i in list  %}
	{{ forloop.counter  }}
	{{ i }}

{% endfor  %}

今日内容

书籍的管理

外键 描述一对多的关系

class Book(models.Model):
    title = models.CharField(max_length=32, unique=True)
    pub = models.ForeignKey('Publisher',on_delete=models.CASCADE)
  
on_delete在2.0版本中是必填的
on_delete=models.CASCADE(级联删除)
		  models.SET()
    	  models.SET_DEFAULT   default=值
		  models.SET_NULL      null=True
          models.DO_NOTHING

展示

    all_books = models.Book.objects.all()  # 对象列表
    for book in all_books:
        print(book)
        print(book.title,type(book.title))
        print(book.pub)     # 外键关联的对象
        print(book.pub_id)  # 关联对象的id  直接从数据库查询

新增

models.Book.objects.create(title=book_name,pub=models.Publisher.objects.get(pk=pub_id))
models.Book.objects.create(title=book_name,pub_id=pub_id)

模板语法

{% if  条件  %}
	满足条件显示的值
{% endif  %}


{% if  条件  %}
	满足条件显示的值
{% else %}
	不满足条件显示的值
{% endif  %}


{% if  条件  %}
	满足条件显示的值
{% elif  条件1  %}
	满足条件显示的值
{% else %}
	不满足条件显示的值
{% endif  %}

day56

内容回顾

1.django处理请求的流程:

  1. 在地址栏中输入地址,回车发送一个请求;
  2. wsgi服务器接收到http请求,封装request对象;
  3. django根据请求的地址找到对应的函数,执行;
  4. 函数执行的结果,django将结果封装成http响应的格式返回给浏览器。

2.发请求的途径

1. 地址栏中输入地址 回车   GET请求

2. a标签  GET请求
3. form表单  GET/POST

3.get和post的区别

​ get 获取页面

​ ?k1=v1&k1=v2 request.GET.get() url 上携带的参数

​ get请求没有请求体

​ post 提交数据

​ 提交的数据 在请求体中

4.函数

def  func(request):
	# 逻辑
	return HttpResponse对象


request.GET    url上携带的参数   {} 
request.POST   POST请求提交的数据    {} 
request.method  请求方法  GET  POST 

HttpResponse('字符串')     返回字符串
render(request,'模板文件的名字',{k1:v1})     返回一个HTML页面
redirect('重定向的地址')    重定向

5.外键

描述 一对多

class Publisher(models.Model):
	name = models.CharField(max_length=32)


class Book(models.Model):
	title = models.CharField(max_length=32)
    pub = models.ForeignKey('Publisher',on_delete=models.CASCADE)    # pub_id

展示

from app01 import models
all_books = models.Book.objects.all()

for book in all_books:
    print(book.id)  print(book.pk)
    print(book)   # 对象  __str__
    print(book.title)   
	print(book.pub)      # 外键关联的对象  print(book.pub.pk)  print(book.pub.name)
    print(book.pub_id)   # 外键关联的对象id

新增

models.Book.objects.create(title='xxxx',pub=关联的对象)
models.Book.objects.create(title='xxxx',pub_id=id)

obj =models.Book(title='xxxx',pub=关联的对象)
obj.save()

删除

models.Book.objects.filter(id=id).delete()
models.Book.objects.filter(id=id).first().delete()

编辑

obj = models.Book.objects.filter(id=id).first()
obj.title = 'xxxxx'
# obj.pub = pub_obj
obj.pub_id = pub_obj.id
obj.save()

6.模板的语法

{{ 变量  }}

for循环
{% for i in list  %}
	{{ forloop.counter  }}
	{{ i }}
{% endfor %}


{%  if 条件 %}
	内容
{% endif %}

{%  if 条件 %}
	内容
{% else %}
	内容2
{% endif %}


{%  if 条件 %}
	内容
{%  elif 条件1 %}
	内容	
{% else %}
	内容2
{% endif %}

今日内容

作者的管理

作者 书籍 多对多的关系

class Author(models.Model):
    name = models.CharField(max_length=32)
    books = models.ManyToManyField('Book')  # 不会生成字段  生成第三张表

展示

all_authors = models.Author.objects.all()
for author in all_authors:
        print(author)
        print(author.name)
        print(author.books,type(author.books))  # 多对多的关系管理对象
        print(author.books.all(),type(author.books.all()))  # 关系对象列表
        

all_books = models.Book.objects.all()
for book in all_books:
	book  # 书籍对象
	book.title
	book.author_set         # 多对多的关系管理对象
	book.author_set.all()   # 书籍关联的所有的作者对象  对象列表  

新增

author_obj = models.Author.objects.create(name=author_name)  # 插入作者信息
author_obj.books.set(book_id) # 设置作者和书籍的多对多的关系

多对多关系表的创建方式:

  1. django自己创建

    class Book(models.Model):
        title = models.CharField(max_length=32, unique=True)
        pub = models.ForeignKey('Publisher', on_delete=models.CASCADE)
     
    
    class Author(models.Model):
        name = models.CharField(max_length=32)
        books = models.ManyToManyField('Book')  # 不会生成字段  生成第三张表
    
  2. 自己手动创建

    class Book(models.Model):
        title = models.CharField(max_length=32, unique=True)
    
    
    class Author(models.Model):
        name = models.CharField(max_length=32)
    
    
    class AuthorBook(models.Model):
        book = models.ForeignKey('Book',on_delete=models.CASCADE)
        author = models.ForeignKey('Author',on_delete=models.CASCADE)
        date = models.CharField(max_length=32)
    
    
  3. 半自动创建(自己手动创建表 + ManyToManyField 可以利用查询方法 不能用set)

    class Book(models.Model):
        title = models.CharField(max_length=32, unique=True)
    
    class Author(models.Model):
        name = models.CharField(max_length=32)
        books = models.ManyToManyField('Book',through='AuthorBook')  # 只用django提供的查询方法  不用创建表 用用户创建的表AuthorBook
    
    class AuthorBook(models.Model):
        book = models.ForeignKey('Book',on_delete=models.CASCADE)
        author = models.ForeignKey('Author',on_delete=models.CASCADE)
        date = models.CharField(max_length=32)
    
    
    class Book(models.Model):
        title = models.CharField(max_length=32, unique=True)
    
    
    class Author(models.Model):
        name = models.CharField(max_length=32)
        books = models.ManyToManyField('Book',through='AuthorBook',through_fields=['author','book'])  # 只用django提供的查询方法  不用创建表 用用户创建的表AuthorBook
    
    
    class AuthorBook(models.Model):
        book = models.ForeignKey('Book',on_delete=models.CASCADE,null=True)
        author = models.ForeignKey('Author',on_delete=models.CASCADE,related_name='x1',null=True)
        tuiianren = models.ForeignKey('Author',on_delete=models.CASCADE,related_name='x2',null=True)
        date = models.CharField(max_length=32)
    
    

周末

学员管理系统

学生表 班级表 教师表

day57

内容回顾

1.django的命令

  1. 下载

    pip install django==1.11.25 -i 源

    1. 创建项目

    django-admin startproject 项目名

  2. 启动项目

    cd 项目的根目录

    python manage.py runserver # 127.0.0.1:8000

    python manage.py runserver 80 # 127.0.0.1:80

    python manage.py runserver 0.0.0.0:80 # 0.0.0.0:80

  3. 创建APP

    python manage.py startapp app名称

  4. 数据库迁移的命令

    python manage.py makemigrations # 检查已经注册的APP下的models.py的变更记录

    python manage.py migrate # 将变更记同步到数据库中

2.django的配置

​ TEMPLATES 模板 DIRS [ os.path.join(BASE_DIR,'templates') ]

​ 静态文件

​ STATIC_URL = '/static/' # 静态文件的别名

​ STATICFILES_DIRS = [

​ os.path.join(BASE_DIR,'static')

​ ]

​ 注册的app

​ INSTALLED_APPS = [

​ 'app01'

​ 'app01.apps.App01Config'

​ ]

​ 中间件

​ 注释掉csrf中间件 可以提交POST请求

​ 数据库的配置

​ ENGINE : mysql

​ NAME: 数据库的名称

​ HOST: ip

​ PORT : 3306

​ USER : 用户名

​ PASSWORD : 密码

3.django使用mysql数据库的流程

  1. 创建一个mysql数据库

  2. 数据库settings中的配置

    ​ ENGINE : mysql

    ​ NAME: 数据库的名称

    ​ HOST: ip

    ​ PORT : 3306

    ​ USER : 用户名

    ​ PASSWORD : 密码

  3. 告诉django使用pymysql连接数据库

    写在与settingst同级目录下的__init__.py中:

    import pymysql

    pymysql.install_as_MySQLdb()

  4. 在models写类(继承models.Model):

    class Publisher(models.Model):
        pid = models.AutoField(primary_key=True)
        name = models.CharField(max_length=32)  # varchar(32)
        
        
    class Book(models.Model):
        title = models.CharField(max_length=32)  # varchar(32)
        pub = models.ForeignKey('Publisher',on_delete=models.CASCADE)
        
        
    class Author(models.Model):
        name = models.CharField(max_length=32)  # varchar(32)
        books = models.ManyToManyField(Book)  # 生成第三张表  不会在Author表中生成字段
    
  5. 执行数据库迁移的命令

    python manage.py makemigrations # 检查已经注册的APP下的models.py的变更记录

    python manage.py migrate # 将变更记同步到数据库中

4.request 请求相关的内容

​ request.GET url上携带的参数 {} get()

​ request.POST POST请求提交的数据 {} get() getlist()

​ request.method 请求方法 GET POST

5.响应

​ HttpResponse(‘字符串’) 返回的字符串‘

​ render(request,'模板的文件名',{}) 返回的是 完整的页面

​ redirect(重定向的地址 ) 重定向

6.ORM

​ 对象关系映射

​ 对应关系:

​ 类 ——》 表

​ 对象 ——》 数据行(记录)

​ 属性 ——》 字段

具体的操作:

查询

from app01 import  models
models.Publisher.objects.all()   #  查询所有的数据  QuerySet  对象列表
models.Publisher.objects.get(name='xxx')   #  查询满足条件的一条数据(唯一存在) 对象 不存在或者多个就报错
ret = models.Publisher.objects.filter(name='xxx')   #  查询满足条件所有的数据   对象列表
ret[0]
ret.first()   #  获取第一个对象  取不到就是None


for i in pubs:
	i.name
    i.pid   i.pk
    
book_obj.title
book_obj.pub    #  外键关联的对象
book_obj.pub_id    #  外键关联对象的id


author_obj.name
author_obj.books   # 关系管理对象
author_obj.books.all()   # 所关联的所有的对象   [book,book]

新增

ret =  models.Publisher.objects.create(name='xxxx')  #  新增数据  返回一个对象
obj = models.Publisher(name='xxxx')
obj.save()

models.Book.objects.create(title='xxxx',pub=出版社对象) 
models.Book.objects.create(title='xxxx',pub_id=出版社对象id) 

obj = models.Author.objects.create(name='xxx')
obj.books.set([book的id])

删除

 models.Publisher.objects.filter(pk=pk).delete()
 book_obj.delete()

编辑

book_obj.title = 'xxxx'
book_obj.pub_id =id
book_obj.save()

author_obj.name='xxx'
author_obj.save()
author_obj.books.set([book的id,book的id,book的id])

7.模板

render(request,'模板的文件名',{k1:v1})

变量
{{  k1 }}

for循环
{% for i in list %}
	{{ forloop.counter }}
	{{ i }}
{% endfor %}

if判读

{% if 条件 %}
	满足条件后的结果
{% endif  %}


{% if 条件 %}
	满足条件后的结果
{% else %}	
	不满足条件后的结果
{% endif  %}


{% if 条件 %}
	满足条件后的结果
{% elif 条件1 %}
	满足条件后的结果	
{% else %}	
	不满足条件后的结果
{% endif  %}

内容回顾

1.MVC和MTV

MVC

​ M: model 模型 数据库交互

​ V:view 视图 展示给用户看的 HTML

​ C :controller 控制器 业务逻辑 传递指令

MTV:

​ M: model 模型 ORM

​ T: template 模板

​ V: view 视图 业务逻辑

2.变量

1.点的使用

{{ 变量 }}

.索引 . key .属性 .方法

优先级:

key > 属性或者方法 > 数字索引

过滤器

{{ value|filter_name }}

{{ value|filter_name:参数 }}

内置的过滤器

https://docs.djangoproject.com/en/1.11/ref/templates/builtins/#built-in-filter-reference

default

{{  变量|default:'默认值'  }}   变量不存在或者为空 显示默认值

filesizeformat

显示文件大小

add

{{ 2|add:'2'  }}   数字加法
{{ 'a'|add:'b'  }}   字符串的拼接
{{ [1,2]|add:[3,4]  }}   列表的拼接

length

返回变量的长度

slice

切片

{{ string|slice:'-1::-1' }}

date 日期格式化

{{ now|date:'Y-m-d H:i:s' }}

safe

{{ a|safe }}  告诉django不需要进行转义 

自定义过滤器
  1. 在app下创建一个名叫templatetags的python包 (templatetags名字不能改)

  2. 在包内创建py文件 (文件名可自定义 my_tags.py)

  3. 在python文件中写代码:

    from django import template
    register = template.Library()  # register名字不能错
    
  4. 写上一个函数 + 加装饰器

    @register.filter
    def str_upper(value,arg):  # 最多两个参数
        ret = value+arg
        return ret.upper()
    

使用:

​ 在模板中

{% load my_tags  %}
{{ 'alex'|str_upper:'dsb'  }}

day58

内容回顾

1.MVC和MTV

MVC:

​ M: model 模型 和数据库交互

​ V: view 视图 展示数据 HTML

​ C: controller 控制器 业务流程 传递指令

MTV:

​ M: model 模型 ORM

T:template 模板  HTML 

​ V : view 视图 业务逻辑

2.模板

变量

render(request,‘模板的文件名’,{ k1:v1 })

{{ 变量 }}

{{ 变量.0 }}

{{ 变量.key }}

{{ 变量.keys }} {{ 变量.values }} {{ 变量.items }}

{{ 变量.属性 }} {{ 变量.方法 }}

优先级:

字典的key > 方法或者属性 > 数字索引

过滤器

修改变量的显示结果

语法:

{{ 变量|filter_name }} {{ 变量|filter_name:参数 }}

内置的过滤器

default 变量不存在或者为空的时候使用默认值 {{ 变量|default :‘默认值’ }}

add + 数字的加法 字符串和列表的拼接

length 返回变量的长度

filesizeformat 文件大小格式化 byte PB

upper lower join

slice 切片 {{ list|slice:'1:2:2' } }

date 日期时间格式化 {{ 日期时间类型|date:'Y-m-d H:i:s' }} datetime: Y-m-d H:M:S

​ settings:

​ USE_L10N = False

​ DATETIME_FORMAT = 'Y-m-d H:i:s'

​ DATE_FORMAT = 'Y-m-d'

safe 前面的内容不用转义 在模板中使用

from django.utils.safestring import mark_safe  # py文件中用

自定义过滤器

  1. 在app下创建一个名为templatetags的python包;

  2. 在包内创建py文件 (任意指定,my_tags.py)

    1. 在py文件中写代码
    from  django import template
    register = template.Library()   #  register名字不能错
    
    1. 写函数 + 加装饰器
    @register.filter
    def str_upper(value,arg):
    	return  ''  
    

使用:

​ 模板中使用:

{% load my_tags  %}
{{ 变量|str_upper:‘参数’ }}

今日内容

{% %} tag

for

{%  for i in list %}
	{{ forloop.counter }}
	{{ i }}
{% endfor  %}

{{ forloop.counter }}      循环的索引 从1开始
{{ forloop.counter0 }}     循环的索引 从0开始
{{ forloop.revcounter }}   循环的索引(倒叙) 到1结束
{{ forloop.revcounter0 }}   循环的索引(倒叙) 到0结束
{{ forloop.first }}        判断是否是第一次循环  是TRUE
{{ forloop.last }}         判断是否是最后一次循环  是TRUE
{{ forloop.parentloop }}   当前循环的外层循环的相关参数
 {% for tr in table %}
            <tr>
                {% for td in tr %}
                    <td > {{ td }} </td>
                {% endfor %}
            </tr>
        {% empty %}
            <tr> <td colspan="4" >没有数据</td> </tr>
{% endfor %}

if

{% if alex.age == 84 %}
    当前已经到了第二个坎了
{% elif alex.age == 73 %}
    当前已经到了第一个坎了
{% else %}
    不在坎上,就在去坎上的路上
{% endif %}

注意:

1. 不支持算数运算  + - * / % 

2. 不支持连续判断    10 > 5 > 1  false

with

{% with p_list.0.name as alex_name %}
    {{ alex_name }}
    {{ alex_name }}
    {{ alex_name }}
    {{ alex_name }}
{% endwith %}

{% with alex_name=p_list.0.name   %}
    {{ alex_name }}
    {{ alex_name }}
    {{ alex_name }}
    {{ alex_name }}
{% endwith %}

csrf 跨站请求伪造

{% csrf_token %}  form表单中有一个隐藏的input标签  name='csrfmiddlewaretoken' value 随机字符串
可以提交post请求

母版和继承

母版:

1. 就是一个HTML页面,提取到多个页面的公共部分;

2. 定义block块,留下位置,让子页面进行填充

继承:

1. 写{% extends  ‘母版的名字’ %}

2. 重写block块

注意点:

​ 1. {% extends 'base.html' %} 母版的名字有引号的 不带引号会当做变量

  1. {% extends 'base.html' %} 上不要写内容,想显示的内容要写在block块中
  2. 多定义点block块,有css js

母版

继承母版

组件

一小段HTML代码 ——》 nav.html

{% include 'nav.html' %}

静态文件

{% load static %}
{% static '相对路径' %}

{% get_static_prefix %}    获取静态文件的别名

simple_tag 和 inclusion_tag

自定义simple_tag:

  1. 在app下创建一个名为templatetags的python包;

  2. 在包内创建py文件 (任意指定,my_tags.py)

  3. 在py文件中写代码

    from  django import template
    register = template.Library()   #  register名字不能错
    
  4. 写函数 + 加装饰器

    @register.simple_tag
    def str_join(*args, **kwargs):
        return '*'.join(args) + '_'.join(kwargs.values())  
        
        
    @register.inclusion_tag('page.html')
    def page(num):
        return {'num':range(1,num+1)}
        
    # 在templates写page.html
    

使用:

​ 模板中使用:

{% load my_tags  %}
{{ 变量|str_upper:‘参数’ }}

{% str_join '1' '2' '3' k1='4' k2='5'  %}

{% page 10 %}

day59

内容回顾

模板

变量

{{ 变量 }}

.key .属性 .方法 .索引

过滤器

{{ 变量|过滤器 }} {{ 变量|过滤器:参数 }}

default add filesizeformart date safe join truncatechars

for 循环

{% for i in list %}

​ {{ i }} {{ forloop }}

{% endfor %}

forloop .counter 当前循环的序号 从1开始

forloop .counter0 当前循环的序号 从0开始

forloop .revcounter 当前循环的序号 到1结束

forloop .revcounter0 当前循环的序号 到0结束

forloop .first 当前循环是否是第一次循环 布尔值

forloop . last 当前循环是否是最后一次循环 布尔值

forloop .parentloop 当前循环的外层循环的参数

for ... empty

{% for i in list %}

​ {{ i }} {{ forloop }}

{% empty %}

​ list 为空的时候

{% endfor %}

if判断

{% if 条件 %}

​ 显示的内容

{% endif %}

{% if 条件 %}

​ 显示的内容

{% elif 条件1 %}

​ 显示的内容

{% endif %}

{% if 条件 %}

​ 显示的内容

{% elif 条件1 %}

​ 显示的内容

{% else%}

​ 显示的内容

{% endif %}

if 要注意的内容:

1. 不支持算数运算 (过滤器) 

2. 不支持连续判断  (10>5>1)

with

{% with alex.name as alex_name %}

​ {{ alex_name }}

{% endwith %}

{% with alex_name=alex.name %}

​ {{ alex_name }}

{% endwith %}

csrf_token

{% csrf_token %}写在form标签内,form标签有一个隐藏的input标签,name=‘csrfmiddlewaretoken’

母版和继承

母版:

​ 本身就是一个HTML页面,提取到多个页面的公共部分,页面中定义多block块。

子页面继承:

1. {% extends  ‘母版文件名’ %}

2. 重写block块

注意点:

1. {% extends  ‘母版文件名’ %}   文件名带引号   不带引号当做变量

2. {% extends  ‘母版文件名’ %}  上面不要写内容   想要显示的内容写在block块中
3. 母版中多定义写block块  css  js

组件

​ 一小段HTML代码段 ——》 HTML文件中

​ {% include 'nav.html' %}

静态文件

​ {% load static %}

​ {% static '相对路径' %}

​ {% get_static_prefix %} STATIC_URL

模板自定义方法

filter simple_tag inclusion_tag

定义:

  1. 在已注册的app下创建templatetags的python包;

  2. 在包中创建py文件 (文件名任意指定 my_tags.py)

  3. 在py文件中写固定的代码:

    from  django  import template
    register = template.Library()   #  register的名字也不能错
    
    1. 写函数 + 加装饰器
    # filter
    @register.filter
    def str_upper(value,arg)  
    	return 'xxxxx'
    
    #simple_tag
    @register.simple_tag
    def str_join(*args,**kwargs):
    	return 'xxxxx'
    
    #inclusion_tag
    @register.inclusion_tag('li.html')
    def show_li(num,*args,**kwargs):
        return {'num':range(1,num+1)}
    
    # li.html
    <ul>
    	{% for i in num %}
        	<li>{{ i }}</li>
        {% endfor %}
    </ul>
    
    

使用:

{% load my_tags  %}

{{ 'xxx'|str_upper:'参数'  }}   

{% str_join 1 2 3 k1=4 k2=5 %}

{% show_li 3 %}
' 
<ul>
	<li>1</li>
	<li>2</li>
	<li>3</li>
</ul>
'

今日内容

视图

MVC MTV

FBV 和 CBV

FBV function based view

CBV class based view

定义CBV

from django.views import View
class PublisherAdd(View):
    
    def get(self,request):
        # 处理get请求的逻辑
        return response
    
    def post(self,request):
        # 处理post请求的逻辑
        return response

写对应关系

 url(r'^publisher_add/', views.PublisherAdd.as_view()),

as_view的流程

  1. 程序加载时,执行View中as_view的方法 ,返回一个view函数。

  2. 请求到来的时候执行view函数:

    1. 实例化类 ——》 self

    2. self.request = request

    3. 执行self.dispatch(request, *args, **kwargs)

      1. 判断请求方式是否被允许:

        1. 允许

          通过反射获取当前对象中的请求方式所对应的方法

          handler = getattr(self, request.method.lower(), self.http_method_not_allowed)

        2. 不允许

          handler = self.http_method_not_allowed

          1. 执行handler 获取到结果,最终返回给django

装饰器补充

from functools import wraps


def wrapper(func):
    @wraps(func)
    def inner(*args, **kwargs):
        # 之前
        ret = func(*args, **kwargs)
        # 之后
        return ret

    return inner

django中给视图加装饰器

FBV 直接给函数添加装饰器

CBV

from django.utils.decorators import method_decorator

  1. 加在方法上

    @method_decorator(wrapper)
    def get(self,request):
    
  2. 加在dispatch方法上

    @method_decorator(wrapper)
        def dispatch(self, request, *args, **kwargs):
            ret = super().dispatch(request, *args, **kwargs)
            return ret
    
    
    @method_decorator(wrapper, name='dispatch')
    class PublisherAdd(View):
    
  3. 加在类上

    @method_decorator(wrapper, name='post')
    @method_decorator(wrapper, name='get')
    class PublisherAdd(View):
    

request

request.method    # 请求方式
request.GET		#  URL上携带的参数
request.POST	# POST请求提交的数据   enctype="application/x-www-form-urlencoded"
request.FILES	# 上传的文件   enctype="multipart/form-data"
request.path_info   # 路径信息  不包含IP和端口  也不包含查询参数
request.body   # 请求体 原始数据
request.COOKIES  # cookies
request.session  # session
request.META   # 请求头的信息

request.get_full_path() # 路径信息  不包含IP和端口 包含查询参数
request.is_ajax()   # 是否是ajax请求 布尔值

response

HttpResponse('字符串')    # 返回字符串
render(request,'模板的文件名',{})   # 返回一个页面
redirect(地址) # 重定向   响应头 Location: 地址

day60

内容回顾

视图

FBV CBV

定义CBV

from django.views import View
class PUblisherAdd(View):
    # http_method_names = ['get',]
    
    def get(self,request,*args,**kwargs):
        # 处理GET请求的具体的逻辑
        self.request
        return response
    
    def post(self,request,*args,**kwargs):
        # 处理GET请求的具体的逻辑
        return response

ulrs.py中写对应关系

url(r'add_publisher/',views.PublisherAdd.as_view())

as_view的流程

  1. 程序启动的时候,类.as_view()方法要执行 ——》 view函数

  2. 请求到来的时候要执行view函数

    1. 实例化类 成对象 ——》 self

    2. self.request = request

    3. 执行dispatch的方法

      1. 判断请求方式是否被允许; http_method_names = []

        1. 允许

          通过反射获取对应请求方式所对应的方法 ——》 handler

        2. 不允许

          http_methid_not_allowed ——》 handler

      2. 执行handler 返回它的执行结果

加装饰器的方法

form functools import wraps

def timer(func):
	@wraps(func)
	def inner(*args,**kwargs):
		# 之前的操作
		ret = func(*args,**kwargs)
		# 之后的操作
		return ret
	return inner

FBV 直接加

CBV

from django.utils.decorators import method_decorator

1. 加在方法上
@method_decorator(timer)
def get(....)

2. 加在类上
@method_decorator(timer,name='get')
class PUblisherAdd(View):

3. 加在dispatch方法上
@method_decorator(wrapper)
def dispatch(self, request, *args, **kwargs):
    ret = super().dispatch(request, *args, **kwargs)
    return ret

@method_decorator(timer,name='dispatch')
class PUblisherAdd(View):

request对象

request.GET   #  url上携带的参数  {} 
request.POST  # POST请求提交的数据   编码类型urlencode
request.method  # 请求方式 POST GET 
request.FILES  # 上传的文件
	1. enctype="multipart/form-data"
    2. input type = 'file'  name='f1'
request.path_info   # 路径信息  不包含ip和端口  也不包含查询的参数
request.body   # 请求体  浏览器提交的原始数据
request.META   # 请求头的信息  小写 ——》  大写  - ——》 _  HTTP_
request.COOKIES  # COOKIE 
request.session  # session 

request.get_full_path()  # 完整的路径信息  不包含ip和端口  包含查询的参数 
request.is_ajax()     # 是否是ajax请求

response对象

HttpRsponse('字符串')     # 返回字符串   Content-Type: text/html; charset=utf-8
render(request,'模板的文件名',{})   # 返回一个HTML页面
redirect(地址)  # 重定向到地址    本质:响应头 Location:地址
JsonResponse({})   # 返回json数据   返回非字典类型safe=False  Content-Type: application/json

路由

URLconf

urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^blog/$', views.blogs),  # /blog/
    url(r'^blog/[0-9]{4}/\d{2}/$', views.blog), # /blog/2019/10/
    
]

url(正则表达式的字符串, 视图函数,)

正则表达式

​ r'' ^ 开通 $ 结尾 [0-9a-zA-Z]{4} \d \w . ? 0个或1个 *0个或无数个 + 至少一个

分组

urlpatterns = [

    url(r'^blog/([0-9]{4})/(\d{2})/$', views.blog),

]

从URL上捕获参数,将参数按照位置传参传递给视图函数。

命名分组

urlpatterns = [

    url(r'^blog/(?P<year>[0-9]{4})/(?<month>\d{2})/$', views.blog),

]

从URL上捕获参数,将参数按照关键字传参传递给视图函数。

include

from django.conf.urls import url, include
from django.contrib import admin

from app01 import views

urlpatterns = [
    url(r'^admin/', admin.site.urls),

    url(r'^app01/', include('app01.urls')),
    url(r'^app02/', include('app02.urls')),

    url(r'^file_upload/', views.file_upload),
    url(r'^get_data/', views.get_data),

]

app01 urls,py

from django.conf.urls import url


from app01 import views

urlpatterns = [

    url(r'^publisher_list/', views.publisher_list),
    # url(r'^publisher_add/', views.publisher_add),
    url(r'^publisher_add/', views.PublisherAdd.as_view()),
    # url(r'^publisher_add/', view),
    url(r'^publisher_del/(\d+)/', views.publisher_del),  
    url(r'^publisher_edit/', views.publisher_edit),
    
]

URL的命名和反向解析

静态路由

URL的命名

url(r'^publisher_list/', views.publisher_list, name='publisher_list'),

URL反向解析

模板

{% url 'publisher_list' %}    ——》  解析生成完整的URL路径  '/app01/publisher_list/'

py文件

from django.shortcuts import render, redirect, HttpResponse, reverse
from django.urls import reverse

reverse('publisher_list')   ——》  '/app01/publisher_list/'

分组

URL的命名

 url(r'^publisher_del/(\d+)/', views.publisher_del,name='publisher_del'),

URL反向解析

模板

{% url 'publisher_del' 1  %}    ——》  解析生成完整的URL路径  '/app01/publisher_del/1/'

py文件

from django.shortcuts import render, redirect, HttpResponse, reverse
from django.urls import reverse

reverse('pub_del',args=(1,))   ——》  '/app01/publisher_del/1/'

命名分组

URL的命名

 url(r'^publisher_del/(\d+)/', views.publisher_del,name='publisher_del'),

URL反向解析

模板

{% url 'publisher_del' 1  %}    ——》  解析生成完整的URL路径  '/app01/publisher_del/1/'
{% url 'publisher_del' pk=1  %}    ——》  解析生成完整的URL路径  '/app01/publisher_del/1/'

py文件

from django.shortcuts import render, redirect, HttpResponse, reverse
from django.urls import reverse

reverse('pub_del',args=(1,))   ——》  '/app01/publisher_del/1/'
reverse('pub_del',kwargs={'pk':1})   ——》  '/app01/publisher_del/1/'

namespace

urlpatterns = [

    url(r'^app01/', include('app01.urls', namespace='app01')),  # home   name=home
    url(r'^app02/', include('app02.urls', namespace='app02')),  # home   name=home

]

反向解析生成URL

{% url 'namespace:name' % }

reverse( 'namespace:name' )

day61

内容回顾

路由系统

urlconf

from django.conf.urls import url

from app01 import views
urlpatterns = [

    url(r'^publisher_list/', views.publisher_list, name='publisher_list'),
    # url(r'^publisher_add/', views.publisher_add),
]

正则表达式

从上到下进行匹配,匹配到一个就不再往下匹配

r $ ^ \d \w [a-z] [azs]{4} . ? + *

分组和命名分组

url(r'^(publisher)_list/', views.publisher_list, name='publisher_list'),

从URL地址上捕获的参数会按照 位置参数 传递给视图函数

url(r'^(?P<xxx>publisher)_list/', views.publisher_list, name='publisher_list'),

从URL地址上捕获的参数会按照 关键字参数 传递给视图函数

include 路由分发

from django.conf.urls import url, include

urlpatterns = [
    url(r'^admin/', admin.site.urls),

    url(r'^app01', include('app01.urls')),
    url(r'^app02/', include('app02.urls')),
]

URL的命名和反向解析

静态路由

url(r'^publisher_list/', views.publisher_list, name='publisher'),

反向解析

模板

{% url 'publisher' %}   ——》 /app01/publisher_list/

py文件

from django.urls import reverse
reverse('publisher')    ——》  /app01/publisher_list/

分组

url(r'^(publisher)_list/', views.publisher_list, name='publisher'),

反向解析

模板

{% url 'publisher' 'publisher' %}   ——》 /app01/publisher_list/

py文件

from django.urls import reverse
reverse('publisher',args=('publisher',))    ——》  /app01/publisher_list/

命名分组

url(r'^(?P<xx>publisher)_list/', views.publisher_list, name='publisher'),

反向解析

模板

{% url 'publisher' 'publisher' %}   ——》 /app01/publisher_list/
{% url 'publisher' xx='publisher' %}   ——》 /app01/publisher_list/

py文件

from django.urls import reverse
reverse('publisher',args=('publisher',))    ——》  /app01/publisher_list/
reverse('publisher',kwargs={'xx':'publisher'})    ——》  /app01/publisher_list/

namespace

urlpatterns = [
    url(r'^admin/', admin.site.urls),

    url(r'^app01', include('app01.urls',namespce='app01')),
    url(r'^app02/', include('app02.urls')),
]

{% url namespace:name %}

reverse('namespace:name ')

今日内容

常用字段

AutoField       自增  primary_key = True主键

IntegerField    整形 -21亿  - 21亿

BooleanField     布尔值类型

NullBooleanField  可以为空的布尔值

CharField      字符串

TextField      文本类型

DateTimeField   日期+加时间

DateField     日期格式
    
TimeField     时间格式

FloatField    浮点型

DecimalField(max_difits=6,decimal_piaces=3)   十进制小数

字段参数

null = True    数据库中该字段可以为空

black = True    用户输入可以为空

default         默认值

db_index=True 索引

unique    唯一约束

verbose_name   显示的名称

choices   可选择的参数

使用admin的步骤:

  1. 创建一个超级用户

    python manage.py createsuperuser
    输入用户名及密码
    

2.在app下的admin.py 中注册model

from django.contrib import admin 
from app01 import models
#Register your models here.
admin.site.register(models.Person)

3.地址栏输入/admin/

必知必会13条

import os

os.environ.setdefault("DJANGO_SETTINGS_MODULE", "about_orm.settings")
import django

django.setup()

from app01 import models

# all()   获取所有的数据  QuerySet  对象列表
ret = models.Person.objects.all()

# get()   获取一个对象  对象  不存在或者多个就报错
# ret = models.Person.objects.get(name='alexdsb')

# filter()   获取满足条件的所有对象  QuerySet  对象列表
ret = models.Person.objects.filter(name='alexdsb')

# exclude()  获取不满足条件的所有对象   QuerySet  对象列表
ret = models.Person.objects.exclude(name='alexdsb')

# values  QuerySet   [ {} ]
# values()  不写参数  获取所有字段的字段名和值
# values('name','age')  指定字段 获取指定字段的字段名和值
ret = models.Person.objects.values('name', 'age')
# for i in ret:
#     print(i,type(i))

# values_list  QuerySet   [ () ]
# values_list()  不写参数  获取所有字段的值
# values_list('name','age')  指定字段 获取指定字段的值

ret = models.Person.objects.values_list('age', 'name')

# for i in ret:
#     print(i, type(i))

# order_by   排序  默认升序   降序 字段名前加-   支持多个字段
ret = models.Person.objects.all().order_by('-age', 'pk')


# reverse  对已经排序的结果进行反转
ret = models.Person.objects.all().order_by('pk')
ret = models.Person.objects.all().order_by('pk').reverse()

# distinct mysql不支持按字段去重
ret = models.Person.objects.all().distinct()

ret = models.Person.objects.values('name','age').distinct()

# count()  计数
ret = models.Person.objects.all().count()
ret = models.Person.objects.filter(name='alexdsb').count()

# first  取第一个元素  取不到是None
ret = models.Person.objects.filter(name='xxxx').first()

# last  取最后一个元素
ret = models.Person.objects.values().first()

# exists  是否存在  存在是True
ret = models.Person.objects.filter(name='xx').exists()
print(ret)


"""
返回对象列表  QuerySet
all()  
filter() 
exclude()
values()    [ {},{} ]
values_list()    [ (),() ]
order_by()
reverse() 
distinct()


返回对象
get
first
last

返回数字
count

返回布尔值
exists() 
"""

单表的双下划线

import os

os.environ.setdefault("DJANGO_SETTINGS_MODULE", "about_orm.settings")
import django

django.setup()

from app01 import models

ret = models.Person.objects.filter(pk__gt=3)  # gt  greater than 大于
ret = models.Person.objects.filter(pk__lt=3)  # lt  less than   小于

ret = models.Person.objects.filter(pk__gte=3)  # gt  greater than equal  大于等于
ret = models.Person.objects.filter(pk__lte=3)  # lt  less than equal    小于等于

ret = models.Person.objects.filter(pk__range=[1, 4])  # 范围
ret = models.Person.objects.filter(pk__in=[1, 4])   # 成员判断
ret = models.Person.objects.filter(name__in=['alexdsb','xx'])

ret = models.Person.objects.filter(name__contains='x')   # contains 包含  like
ret = models.Person.objects.filter(name__icontains='X')   # ignore contains 忽略大小写

ret = models.Person.objects.filter(name__startswith='X')   # 以什么开头
ret = models.Person.objects.filter(name__istartswith='X')   # 以什么开头

ret = models.Person.objects.filter(name__endswith='dsb')   # 以什么开头
ret = models.Person.objects.filter(name__iendswith='DSB')   # 以什么开头


ret = models.Person.objects.filter(phone__isnull=False)   # __isnull=False  不为null

ret = models.Person.objects.filter(birth__year='2020')
ret = models.Person.objects.filter(birth__contains='2020-11-02')
print(ret)

188 0133 8917

188 4321 2314

186 2314 3200

day62

内容回顾

ORM

对象关系映射 面向对象和关系型数据库

对应关系

类 ——》 表

对象 ——》 数据行(记录)

属性 ——》 字段

常用字段

models.AutoField(primary_key=True)
models.CharField(max_length) # 字符串 varchar(32)
models.TextField  
models.BooleanField  # 布尔值
models.DateTimeField(auto_now=True)
models.IntegerField  # 10  -21亿  + 21亿
models.FloatField  
models.DecimalField(max_digits=6,decimal_places=3)  # 10进制  999.999
models.ForeignKey  
models.ManyToManyField

字段的参数

null=True    数据库中该字段可以为空
blank = True   form表单输入时允许为空
default    默认值
unique     唯一
choices    可选的参数
verbose_name  可显示的名字
db_index 数据库索引
db_column     列名
editable  是否可编辑

必知必会13条

返回querySet

all()      所有的对象
filter()    获取满足条件的所有对象
exclude()   获取不满足条件的所有对象
order_by()   排序   - 
reverse()   反转
values()    [ {}  ]
values_list()    [ ()  ]
distinct()   去重  不能按照字段去重

返回对象

get()    获取有且唯一的对象
first()
last()

返回数字

count()

返回布尔值

exists()

单表的双下划线

字段__条件
__gt   大于
__gte   大于等于
__lt  小于
__lte   小于等于
__in= []    成员判断
__range = [3,6]  范围  3-6

__contains =''    包含   like
__icontains =''   忽略大小写

__startswith =''   以什么开头
__istartswith =''   以什么开头


__endswith =''   以什么结尾
__endswith =''   以什么结尾


__year ='2019'  

__isnull = True   字段值为null 

外键

# 基于对象的查询
# 正向查询
book_obj = models.Book.objects.get(pk=4)
print(book_obj.name)
print(book_obj.publisher)
print(book_obj.publisher_id)

# 反向查询
pub_obj = models.Publisher.objects.get(pk=1)
# 不指定related_name  表名小写_set
print(pub_obj)
print(pub_obj.book_set)   # 表名小写_set   关系管理对象
print(pub_obj.book_set.all())

# 指定related_name=‘books’  表名小写_set
print(pub_obj.books)
print(pub_obj.books.all())


# 基于字段的查询
# 查询“李小璐出版社”出版社的书
ret = models.Book.objects.filter(publisher__name='李小璐出版社')

# 查询“绿光”书的出版社
# 没有指定related_name  表名小写
ret = models.Publisher.objects.filter(book__name='绿光')

# 指定related_name='books'
ret = models.Publisher.objects.filter(books__name='绿光')

# 指定related_query_name='book'
ret = models.Publisher.objects.filter(book__name='绿光')

print(ret)

多对多

# 基于对象的
author_obj = models.Author.objects.get(name='yinmo')
# print(author_obj.books)     # 关系管理对象
# print(author_obj.books.all())  # 所关联的书

book_obj = models.Book.objects.get(name='原谅你')
# print(book_obj.author_set)
# print(book_obj.author_set.all())

# print(book_obj.authors)
# print(book_obj.authors.all())

# 基于字段的查询
# print(models.Author.objects.filter(books__name='原谅你'))
# print(models.Book.objects.filter(author__name='yinmo'))

# all 查询所有的对象

# set()  设置多对多的关系   [id,id]   [对象,对象]
# author_obj.books.set([1,3])
# author_obj.books.set(models.Book.objects.filter(pk__in=[2,4]))

# add  新增多对多的关系   id,id   对象,对象
# author_obj.books.add(1,3)
# author_obj.books.add(*models.Book.objects.filter(pk__in=[1,3]))

# remove  删除多对多的关系   id,id   对象,对象
# author_obj.books.remove(1,3)
# author_obj.books.remove(*models.Book.objects.filter(pk__in=[2,4]))

# clear  删除所有多对多的关系
# author_obj.books.clear()
# author_obj.books.set([])

# create  创建一个所关联的对象并且和当前对象绑定关系
# ret = author_obj.books.create(name='yinmo的春天',publisher_id=1)
# print(ret)

pub_obj = models.Publisher.objects.get(pk=1)
print(pub_obj.books.all())
# print(pub_obj.books.set(models.Book.objects.filter(pk__in=[3,4])))
# print(pub_obj.books.add(*models.Book.objects.filter(pk__in=[1])))

# 外键的关系管理对象需要有remove和clear 外键字段必须可以为空
# print(pub_obj.books.remove(*models.Book.objects.filter(pk__in=[1])))
# print(pub_obj.books.clear())

# print(pub_obj.books.create(name="你喜欢的绿色"))

聚合和分组

# 所有的价格

# ret = models.Book.objects.all().aggregate(Sum('price'))
# ret = models.Book.objects.all().aggregate(sum=Sum('price'),avg=Avg('price'),count=Count('pk'))
# ret = models.Book.objects.filter(pk__in=[1,2]).aggregate(sum=Sum('price'),avg=Avg('price'),count=Count('pk'))

# print(ret,type(ret))

# 分组
# 每一本书的作者个数
ret = models.Book.objects.annotate(count=Count('author'))

# 统计出每个出版社买的最便宜的书的价格
# 方式一
ret = models.Publisher.objects.annotate(Min('book__price')).values()
# for i in ret:
#     print(i)
# 方拾二
# ret = models.Book.objects.values('publisher__name').annotate(min=Min('price'))


# 统计不止一个作者的图书

ret = models.Book.objects.annotate(count=Count('author')).filter(count__gt=1)


# 查询各个作者出的书的总价格

ret = models.Author.objects.annotate(Sum('books__price')).values()

print(ret)


F和Q


from django.db.models import F, Q

ret = models.Book.objects.filter(sale__gt=F('kucun'))

ret = models.Book.objects.all().update(publisher_id=3)

ret = models.Book.objects.filter(pk=1).update(sale=F('sale')*2+43)

# & 与  and
# | 或  or
# ~ 非  not
# Q(pk__gt=5)
ret = models.Book.objects.filter(Q(~Q(pk__gt=5) | Q(pk__lt=3)) & Q(publisher_id__in=[1, 3]))

print(ret)


事务

from django.db import transaction


try:
    with transaction.atomic():
        # 一系列的操作
        models.Book.objects.update(publisher_id=4)
        models.Book.objects.update(publisher_id=3)
        int('ss')
        models.Book.objects.update(publisher_id=2)
        models.Book.objects.update(publisher_id=5)

except Exception as e:
    print(e)

day63

定义:

​ 保存在浏览器本地上的一组组键值对

特性:

	1. 服务器让浏览器进行设置的 

 		2. 下次访问时自动携带相应的cookie

在django的操作:

  1. 获取

    request.COOKIES {}

    request.COOKIES[] .get

    request.get_signed_cookie(key,salt='...',default='xxx')

  2. 设置

    response.set_cookie(key,value)

    response.set_signed_cookie(key,value,salt='...')

  3. 删除cookie

    response.delete_cookie(key)

    from django.shortcuts import render, redirect, HttpResponse
    
    from functools import wraps
    
    
    # Create your views here.
    
    
    def is_loging(func):
        @wraps(func)
        def inner(request, *args, **kwargs):
            is_login = request.COOKIES.get('is_login')
            if is_login != 'true':
                         return redirect('/login/?indexUrl'.format(request.path_info))
                
                #request.path_info  帮助生成url
            ret = func(request, *args, **kwargs)
            return ret
    
        return inner
    
    
    def login(request):
        if request.method == 'POST':
            user = request.POST.get('user')
            pwd = request.POST.get('pwd')
    
            if user == 'alex' and pwd == 'alex3714':
                # 保存登录状态  设置 cookie
               returnUrl = request.GET.get('indexUrl')
               ret = redirect( returnUrl if returnUrl else '/home/')
    
                #获取GET请求中的url地址,有地址的返回url携带的地址,如果没有就走home地址
                ret.set_cookie('is_login', 'true')
    
                return ret
    
            return render(request, 'login.html', {'error': '用户名密码错误'})
    
        return render(request, 'login.html')
    
    
    @is_loging
    def home(request):
        return HttpResponse('这是home页面')
    
    

session

定义:

​ 保存在服务器上的一组组键值对,必须依赖cookie

Django的使用:

  1. 设置

​ request.session[key] = value

  1. 获取

    request.session[key]

    request.session.get(key)

  2. 其他

    del request.session['k1']
    # 会话session的key
    request.session.session_key
    
    # 将所有Session失效日期小于当前日期的数据删除
    request.session.clear_expired()
    
    # 删除当前会话的所有Session数据
    request.session.delete()
      
    # 删除当前的会话数据并删除会话的Cookie。
    request.session.flush() 
    
    # 设置会话Session和Cookie的超时时间
    request.session.set_expiry(value)
        * 如果value是个整数,session会在些秒数后失效。
        * 如果value是个datatime或timedelta,session就会在这个时间后失效。
        * 如果value是0,用户关闭浏览器session就会失效。
        * 如果value是None,session会依赖全局session失效策略。
    

session的配置

from django.conf import global_settings

cookie名字
SESSION_COOKIE_NAME = 'sessionid'
超时时间
SESSION_COOKIE_AGE = 60 * 60 * 24 * 7 * 2
每次请求保存session
SESSION_SAVE_EVERY_REQUEST = False
浏览器关闭session数据失效
SESSION_EXPIRE_AT_BROWSER_CLOSE = False
存放session的位置
SESSION_ENGINE = 'django.contrib.sessions.backends.db'


day64

cookie和session

  1. 定义

    保存在浏览器上的一组组键值对

  2. 为什么要有?

    HTTP协议是无状态,每次请求之间都相互独立的,之间没有关系,没办法保存状态。

  3. 特性:

    1. 服务器让浏览器进行设置,浏览器有权利不保存
    2. 下次访问时,自动携带响应的cookie
    3. 保存在浏览本地的
  4. django的操作:

    1. 设置 set-cookie

      response.set_cookie(key,value,max_age=5,path='/')

      response.set_signed_cookie(key,value,max_age=5,path='/',salt='xxxxx')

    2. 获取 cookie

      request.COOKIES {}

      request.COOKIES[key] request.COOKIES.get(key)

      request.get_signed_cookie(key,salt='xxxxx',default=‘’)

    3. 删除 set-cookie

      response.delete-cookie(key')

session

  1. 定义:

    ​ 保存在服务器上的一组组键值对,必须依赖cookie

  2. 为什么要有?

    1. cookie保存在浏览器上,不太安全
    2. 浏览器对cookie的大小有一定的限制
  3. session的流程:

    1. 浏览器发送请求,没有cookie也没有session
    2. 要设置session时,先根据浏览器生成一个唯一标识(session_key),存键值对,并且有超时时间
    3. 返回cookie session_id = 唯一标识
  4. 在django中的操作:

    1. 设置

      request.session[key] = value

    2. 获取

      request.session[key] request.session.get()

    3. 删除

      del request.session[key]

      request.session.pop(key)

      request.session.delete() 删除所有的session 不删除cookie

      request.session.flush() 删除所有的session 删除cookie

    4. 其他

      request.session.clear_expired() 删除已经失效的session数据

      request.session.set_expiry(value)

    5. 配置

      from django.conf import global_settings

    ​ SESSION_SAVE_EVERY_REQUEST = True 每次请求都更新session数据

    ​ SESSION_EXPIRE_AT_BROWSER_CLOSE = True

    ​ SESSION_ENGINE = 'django.contrib.sessions.backends.db' 默认存在数据库

    ​ 缓存 文件 缓存+数据库 加密cookie

    ​ Json序列化的过程

中间件

中间件 :中间件就是一个类,在全局范围内处理django的请求和响应。

类 5个方法 4个特点

规律:
    
#在你视图函数之前执行的这些方法按照顺序执行,

#在视图函数执行之后的这些方法按照倒序执行

process_request(self,request)

执行时间:

​ 在视图函数之前

执行顺序:

​ 按照注册的顺序 顺序执行

参数 :

​ request: 请求的对象,和视图函数是同一个

返回值:

​ None : 正常流程

​ HttpResponse:之后中间件的process_request、路由、process_view、视图都不执行,执行执行当前中间件对应process_response方法,接着倒序执行之前的中间件中的process_response方法。

中间件--> 浏览器发送请求回复响应,之前是在视图里回复响应的,写到中间件里会响应,后面要做的事就不用做了!

process_response(self, request, response)

执行时间:

​ 在视图函数之后

执行顺序:

​ 按照注册的顺序 倒序执行

参数 :

​ request: 请求的对象,和视图函数是同一个

​ response: 响应对象

返回值:

​ HttpResponse: 必须返回

返回值可以是别人传过来的response 
也可以自己返回	HttpResponse

process_view(self, request, view_func, view_args, view_kwargs)

执行时间:

​ 在路由匹配之后,在视图函数之前

执行顺序:

​ 按照注册的顺序 顺序执行

参数 :

​ request: 请求的对象,和视图函数是同一个

​ view_func:视图函数

​ view_args: 给视图传递的位置参数

​ view_kwargs: 给视图传递的关键字参数

返回值:

​ None: 正常流程

​ HttpResponse: 之后中间件的process_view、视图都不执行,直接执行最后一个中间件process_response,倒序执行之前中间件的process_response方法

process_exception(self, request, exception)

执行时间:

​ 在视图函数出错之后执行

执行顺序:

​ 按照注册的顺序 倒序执行

参数 :

​ request: 请求的对象,和视图函数是同一个

​ exception:报错的对象

返回值:

​ None: 自己没有处理,交给下一个中间件处理,所有的中间件都没有处理,django处理错误。

​ HttpResponse: 之后中间件的process_exception,直接执行最后一个中间件process_response,倒序执行之前中间件的process_response方法

process_template_response(self,request,response)

执行时间:

​ 当视图函数返回一个TemplateResponse对象

执行顺序:

​ 按照注册的顺序 倒序执行

参数 :

​ request: 请求的对象,和视图函数是同一个

​ response:响应的对象

返回值:

​ HttpResponse: 必须返回

day65

Ajax

js的技术,就是发请求接受响应的技术,传输少量的数据。

发请求的途径:

  1. a标签 get
  2. 地址栏输入地址 get
  3. form表单 get / post

特点:

  1. 局部刷新

  2. 传输的数据量少

  3. 异步

简单使用:

$.ajax({
            'url':'/calc/',
            'type':'post',
            'data':{
                'k1':$('[name="i1"]').val(),
                'k2':$('[name="i2"]').val(),
            },
            success:function (ret) {
               $('[name="i3"]').val(ret)
            }
        })

参数

$.ajax({
            url: '/test/',   	#  提交的地址
            type: 'post',		#  请求方式
            data: {				#  提交的数据
                name: 'alex',
                age: 73,
                hobby: JSON.stringify(['装逼', '画饼', '上过北大'])
            },
            success: function (ret) {		# 响应成功的回调函数

            },
            error:function (ret) {			# 响应失败的回调函数
                console.log(ret)
            }
        })

上传文件

$('button').click(function () {

        var form_data = new FormData();
        form_data.append('k1','v1');
        form_data.append('f1',$('#f1')[0].files[0]);

        $.ajax({
            url :'/file_upload/',
            type:'post',
            data:form_data,  // { k1:v1 }
            processData: false,  //   不需要处理数据
            contentType: false,  //   不需要contentType请求头
            success:function (ret) {
                console.log(ret)
            }

        })

    })

ajax能通过django的csrf的校验:

前提必须有cookie:

  1. 给视图加装饰器

    from django.views.decorators.csrf import ensure_csrf_cookie
    
    @ensure_csrf_cookie
    def index(request):
    

方式一:data中添加键值对 csrfmiddlewaretoken

$.ajax({
            'url': '/calc/',
            'type': 'post',
            'data': {
                'csrfmiddlewaretoken': $('[name="csrfmiddlewaretoken"]').val(),
                'k1': $('[name="i1"]').val(),
                'k2': $('[name="i2"]').val(),
            },
            success: function (ret) {
                $('[name="i3"]').val(ret)
            }
        })

方式二:加请求头 x-csrftoken

$('#b2').click(function () {
        // 点击事件触发后的逻辑
        $.ajax({
            'url': '/calc2/',
            'type': 'post',
            headers:{'x-csrftoken':$('[name="csrfmiddlewaretoken"]').val(),},
            'data': {
                'k1': $('[name="ii1"]').val(),
                'k2': $('[name="ii2"]').val(),
            },
            success: function (ret) {
                $('[name="ii3"]').val(ret)
            }
        })

    })

方式三:

导入文件

day66

内容回顾

ajax

js技术,发请求。

特点:

  1. 异步

  2. 局部刷新

  3. 数据量小

发请求的方式:

  1. 地址栏输入地址 get
  2. a标签 get
  3. form get /post
    1. action 提交的地址 method='post' 上传的文件的 enctype="multipart/form-data"
    2. 有button或者 input类型submit
    3. input 标签有name属性 有的需要有value
  4. ajax

简单使用:

使用jq发送ajax请求

$.ajax({
    url:'' ,  //  请求发送的地址
    type:'post',   //  请求方式
    data: {} ,  //  数据
    success:function (res){}      //  响应成功之后执行的回调函数  res返回的响应体 
    
})

上传文件

var form_data  =  new FormData()
form_data.append('k1','v1')
form_data.append('f1',$('#f1')[0].files[0])

$.ajax({
    url:'' ,  //  请求发送的地址
    type:'post',   //  请求方式
    data:form_data ,  //  数据
    processData:false,   //  不需要处理数据的编码 multipart/form-data
    contentType:false,   //  不需要处理contentType的请求头
    success:function (res){}      //  响应成功之后执行的回调函数  res返回的响应体 
    
})

ajax通过django的csrf的校验

前提:必须要有csrftoken的cookie

方式一:

给data添加csrfmiddlewaretoken键值对

方式二:

给headers 添加 x-csrftoken的键值对

方式三:

导入文件

csrf相关装饰器

from django.views.decorators.csrf import ensure_csrf_cookie,csrf_exempt,csrf_protect

# ensure_csrf_cookie  确保有cookie
# csrf_exempt   不需要进行csrf的校验
# csrf_protect  需要进行csrf的校验

注意:  csrf_exempt CBV的时候只能加载dispatch方法上

今日内容

form组件

form

  1. 有input让用户输入
  2. 提交数据

form组件

  1. 提供input框
  2. 能对数据做校验
  3. 返回错误提示

定义:定义是在views.py中

from django import forms
class RegForm(forms.Form):
    username = forms.CharField(label='用户名')
    password = forms.CharField(label='密码')

使用:

函数
def register2(request):
    if request.method == 'POST':
        form_obj = RegForm(request.POST)

        if form_obj.is_valid():  # 校验数据
            # 插入数据库
            print(form_obj.cleaned_data)
            print(request.POST)

            return HttpResponse('注册成功')
    else:
        form_obj = RegForm()
    return render(request, 'register2.html', {'form_obj': form_obj})

模板
{{ form_obj.as_p }}   # 展示所有的字段

{{ form_obj.username }}           #  生成input框
{{ form_obj.username.label }}     #  中文提示
{{ form_obj.username.id_for_label }}    # input框的id
{{ form_obj.username.errors }}     # 该字段的所有的错误
{{ form_obj.username.errors.0 }}    # 该字段的第一个的错误

{{ form_obj.errors }}    # 该form表单中所有的错误

常用字段:

CharField      # 文本输入框
ChoiceField    # 单选框
MultipleChoiceField  # 多选框

字段参数:

    required=True,               是否必填
    widget=None,                 HTML插件
    label=None,                  用于生成Label标签或显示内容
    initial=None,                初始值
    error_messages=None,         错误信息 {'required': '不能为空', 'invalid': '格式错误'} 
    disabled=False,              是否可以编辑
    validators=[],               自定义验证规则


校验

自定义校验规则

  1. 写函数

    from django.core.exceptions import ValidationError/校验
    
    def checkusername(value):
    	# 通过校验规则  什么事都不用干
    	# bu通过校验规则  抛出异常ValidationError
        if models.User.objects.filter(username=value):
            raise/抛出异常/ ValidationError('用户名已存在')
            
    username = forms.CharField(
    
            validators=[checkusername,])
    
    

  1. 用内置的校验器

    from django.core.validators import RegexValidator
    
    phone = forms.CharField(min_length=11,max_length=11,validators=[RegexValidator(r'^1[3-9]\d{9}$','手机号格式不正确')])
    
    
    

局部钩子和全局钩子(推荐使用)

    def clean(self):
        # 全局钩子
        # 通过校验   返回self.cleaned_data
        # 不通过校验   抛出异常
        password = self.cleaned_data.get('password')
        re_password = self.cleaned_data.get('re_password')
        if password == re_password:
            return self.cleaned_data
        else:
            self.add_error('password','两次密码不一致!!')
            raise ValidationError('两次密码不一致')

    def clean_username(self):
        # 局部钩子
        # 不通过校验   抛出异常
         # 通过校验   返回当前字段的值
        value = self.cleaned_data.get('username')
        #获取存放有效数据的那些字典找他得值
        if models.User.objects.filter(username=value):
            raise ValidationError('用户名已存在')
        return value

局部钩子

#小点:
自定义的函数校验器,需要填红色的框框,也是针对于某一个字段,别的字段要用,就得加validators=[自定义校验器函数]

form组件,局部钩子,只针对于某一个字段进行校验
上面这个局部钩子只是正对于username这个字段进行的校验!

day67

django web框架

功能

  1. socket收发消息 wsgi
  2. 根据不同的路径返回不同的内容
  3. 返回动态页面(字符串的替换 模板的渲染)

在浏览器上的地址输入地址回车会发生什么事情?

HTTP协议

超文本传输协议 规定请求和响应的格式

请求(浏览器发送给服务器的消息 request)

格式:

'请求方式 URL路径 HTTP/1.1

K1: v1

k2: v2

请求体(请求数据)' // get方法没有请求体

响应(服务器返回给浏览器的消息 response)

格式

‘HTTP/1.1 状态码 状态描述

K1: v1

k2: v2

响应体(响应数据)’

请求方式:8种 GET POST PUT DELETE HEAD OPTION TRACE CONNECT

状态码:

1xx 请求已经接受 还需要进一步的处理

2xx 请求正常接受并且响应

3xx 重定向 301 302

4xx 请求的错误 403 404 402

5xx 服务器的错误 500 502

头:

location 重定向

cookie set-cookie

x-csrftoken

content-type text/html applicaton/json

user-agent

host

url地址:

https://www.baidu.com/s?ie=utf-8&f=8&rsv_bp=1&rsv_idx=1&tn=baidu

http 80

https 443

django

路由

URL地址和函数的对应关系

URLconf

urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^publisher/(\d+)/$',views.register ),
    url(r'^register2/$',views.register2 ),
]

正则表达式

^ $ \d \w  ? + * . |

分组和命名分组

捕获参数 ?id=1111

分组 () 按照位置传参 传给视图

命名分组 (?P ) 按照关键字传参 传给视图

路由分发 include

urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^app01/',include('app01.urls') ),
]

app01 urls.py

urlpatterns = [
    url(r'^register2/$',views.register2 ),
]

URL的命名和反向解析

静态路由

命名

    url(r'^register2/$',views.register2,name='reg' ),

反向解析

模板

 {% url 'reg' %}   #   '/app01/register2/'

py文件

from django.urls  import reverse
reverse('reg')   #   '/app01/register2/'

分组

命名

 url(r'^register(\d+)/$',views.register2,name='reg' ),

反向解析

模板

 {% url 'reg' 20  %}   #   '/app01/register20/'

py文件

from django.urls  import reverse
reverse('reg',args=('30',))   #   '/app01/register30/'

命名分组

命名

 url(r'^register(?P<pk>\d+)/$',views.register2,name='reg' ),

反向解析

模板

 {% url 'reg' 20  %}   #   '/app01/register20/'
 {% url 'reg' pk=20  %}   #   '/app01/register20/'

py文件

from django.urls  import reverse
reverse('reg',args=('30',))   #   '/app01/register30/'
reverse('reg',kwargs={‘pk’:'30'}   #   '/app01/register30/'

namespace

urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^app01/',include('app01.urls',namespace='app01') ),
    url(r'^app02/',include('app02.urls',namespace='app02') ),
]

反向解析

{% url 'app01:reg' 20 %}

reverse('app01:reg',args=('30',))

视图

MVC

MTV

view 逻辑 接受请求返回响应

FBV CBV

def xxx(request,*args,**kwargs):
	# 逻辑
	return response

url(r'^xxx/',xxx ),
from django.views import View
class Class(View):

	def get(self,request,*args,**kwargs):
        # 处理get请求的逻辑
        self.request
		return response
    
    def post(self,request,*args,**kwargs):
        # 处理post请求的逻辑
		return response

url(r'^xxx/',Class.as_view()),

加装饰器

from django.utils.decorators import method_decorator
  1. 加在方法上

    @method_decorator(timer)
    def get(self,request,*args,**kwargs):
    
  2. 加在类上

    @method_decorator(timer,name='get')
    @method_decorator(timer,name='post')
    class Class(View):
    
  3. 加在dispatch

    @method_decorator(timer,name='dispatch')
    class Class(View):
    

request

request.POST    #  POST提交的数据 {}    urlencode编码
request.GET     #   url上携带的参数  ?id=1  {id:1}
request.method  #  请求方法  GET POST
request.path_info  # 路径信息  不包含IP和端口 也不包含查询参数
request.FILES   # 上传的文件 enctype='form-data'
request.session  # {}  session 
request.COOKIES  # cookie  
request.META   # 请求头的信息  HTTP_  小写——》  大写  - ——》 _
request.body  # 请求体  原始数据

request.get_full_path()  #  完整的路径信息 不包含IP和端口 包含查询参数
request.is_ajax()  # 是否是ajax请求
request.get_signed_cookie(key,salt,defalut='')

response

HttpResponse('字符串')   #  字符串
JsonResponse({})   JsonResponse([],safe=False) 
render(request,'模板文件的路径',{})   # 返回页面 已经替换好了
redirect('地址或者URLname')   # 重定向  响应头Location:地址 301 302 
TemplateResponse(request,'模板文件的路径',{})  # 后续在调用render方式进行渲染

模板

html + 特殊的语法

变量

{{ }} 变量 {% %}

.key .属性 .方法 .索引

过滤器

内置过滤器

safe default filesizeformat date:'Y-m-d H:i:s' add length slice:'::' join

标签

for forloop

for ... empty

if

不支持算数运算 连续判断

母版和继承

母版:

1. 写上一个HTML页面,包含多个页面的公共部分

2. 定义多个block块,让子页面进行重写

继承:

1. {% extends '母版的路径' %}

2. 重写block块

组件

一段HTML代码 ——》 文件 nav.html

页面 {% include ‘nav.html’ %}

静态文件

{% load static %}

{% static '相对路径' %}

{% get_static_prefix %} # STATIC_URL ='/static/'

自定义的方法

filter、simple_tag 、inclusion_tag

定义:

  1. 在已经注册的APP下创建templatetags的python包;

  2. 在python包中创建py文件(自己定义my_tags)

  3. 写代码

    from  django import template
    register = template.Library() 
    
  4. 写函数 +加装饰器

    @register.filter
    def add_arg(value,arg):
    	return 'xxxx'
    
    
    @register.simple_tag
    def joins(*args,**kwargs):
    	return 'xxxxxxx'
    
    
    @register.inclusion_tag('li.html')
    def show_li(*args,**kwargs):
    	return {'li':[1,2]}
    
    li.html
    {% for i in li %}
    	{{ i }}
    {% endfor %}
    
    

使用:

模板

{% load my_tags %}

{{ a|add_arg:'xxx' }}   # 'xxxx'

{% joins 'v1' 'v2' k1='v3' k2='v4'  %}  # 'xxxxxxx'

{% show_li 3 %}   #  1 2 

ORM

对象关系映射

对应关系

类 ——》 表

对象 ——》 数据行(记录)

属性 ——》 字段

必知必会13条

返回对象列表 QuerySet

all

filter

exculde

values 【{}】

values_list 【() 】

order_by()

reverse()

distinct 去重

返回对象

get

first

last

返回布尔值

exists

返回数字

count

单表的双下划线

__gt 大于
__gte 大于等于
__lt  小于
__lte   小于等于
__in= []   在不在成员判断
__range = [1,6]   范围
__startswith  以什么开头 __istartswith  以什么开头
__endswith  以什么结尾 __iendswith  以什么结尾
__contains  包含 like __icontains 
__year   年
__isnull=True 

外键的操作

class Book(models.Model):
	name= models.CharField(max_length=32)
	pub= models.ForginKey(to='Publisher',on_delete=models.CASCADE,related_name='books')

基于对象

正向
book_obj.pub      ——》 关联的出版社对象
book_obj.pub_id   ——》 关联的出版社对象id
反向
不指定 related_name
pub_obj.book_set        ——》 关系管理对象
pub_obj.book_set.all()  ——》 关联的所有的书籍对象  表名_set 
指定related_name='books'
pub_obj.books.all()  ——》 关联的所有的书籍对象  related_name

基于字段

models.Book.objects.filter(pub__name='xxx')
models.Publisher.objects.filter(book__name)  不指定 related_name
models.Publisher.objects.filter(books__name)  指定 related_name='books'

多对多

class Book(models.Model):
	name= models.CharField(max_length=32)
	
class Author(models.Model):
	name= models.CharField(max_length=32)
	books= models.ManyToManyField('Book',related_name='authors')

all()

set([]) [对象,对象] [id,id ]

add()

remove()

clear()

create()

聚合和分组

from django.db.models import  Max,Min,Count,Avg,SumHobby.objects.all().aggregate(max=Max('filed'))  # {max:'xxx'  }
Author.objects.annotate(count=Count('books'))  # 对象列表

Book.objects.values('authors__name').annotate(Min('price'))   # [{}]

F和Q

Book.objects.update(price=F('price')+2)

Q(Q(price__gt=10)|Q()) 
| 或
& 与
~ 非

事务

一系列的操作 要么都成功,要么都失败。

from django.db import transaction

try:
    with transaction.atomic():
        # 一系列操作
        pass

except Exception as e:
    print(e)

中间件

处理django请求和响应的框架级别的钩子。

5个方法 4个特征

cookie和session

为什么要有cookie?

定义:保存在浏览器上一组组键值对

特点:

1. 由服务器让浏览器进行设置

2. 保存在浏览器本地的
3. 下次访问时自动携带对应的cookie

django中的操作:

  1. 设置 set-cookie

    response.set_cookie(key,v,max-age=5,path='/')
    
  2. 获取

    request.COOKIES[]  get()
    
  3. 删除 set-cookie

    response.delete_cookie(key)
    

session

为什么要有session?

定义:保存在服务器上一组组键值对,必须依赖cookie

django中的操作:

  1. 设置

    request.session[key] = value

  2. 获取

    request.session[key] request.session.get(key)

  3. 删除

    del request.session[key]

    request.session.pop(key)

    request.session.delete()

    request.session.flush()

    request.session.clear_expired() # 删除已经过期的数据

  4. request.session.set_expiry()

配置

​ 引擎 SESSION_ENGINE 位置 数据库 缓存 文件 缓存+数据库 加密cookie

​ SESSION_SAVE_EVERY_REQUEST = True

​ SESSION_EXPIRE_AT_BROWSER_CLOSE = True

​ json序列化

ajax

js技术 ,发请求。

$.ajax({
    url: 地址,
    type:  请求方式,
    data : {},
    success:function (res){  
        # 逻辑
        $(this)
    }
    
})


$.ajax({
    url: 地址,
    type:  请求方式,
    data : {},
    success: (res) => {  
        # 逻辑
        $(this)
    }
    
})

ajax通过django的csrf的校验

  1. 给data 加
  2. 加请求头 x-csrftoken

form

功能:

  1. 提供input框
  2. 校验forms
  3. 错误提示
from django import forms
class RegForm(forms.Form):
    name  = forms.CharField(widget=)
    
    def clean_字段名(self):
        # 校验规则
        # 通过校验  返回当前字段的值
    	# 不通过校验  抛出异常  
    
    def clean(self):
        # 校验规则
        # 通过校验  返回所有字段的值self.cleaned_data
    	# 不通过校验  抛出异常   __all__   self.add_error('字段',’错误信息‘)
label 	中文提示
initial  初始值
required  必填
error_messages = { }   
disabled  
validators 校验器 

视图

form_obj = RegForm()


form_obj = RegForm(request.POST)
form_obj.is_valid()  
form_obj.cleaned_data  通过校验的数据

模板

{{ form_obj.as_P }}

{{ form_obj.name }}          input框
{{ form_obj.name.label }}     中文提示
{{ form_obj.name.id_for_label }}     input框的id
{{ form_obj.name.errors }}    当前字段的所有错误
{{ form_obj.name.errors.0 }}  当前字段的第一个错误

{{ form_obj.errors }}    所有字段的所有错误

校验顺序

每个字段:

​ 内置校验规则 field.validate(必填 长度 )

  校验器field.run_validators(默认校验器,自定义的校验器) 

​ 局部钩子form_obj.clean_字段名

全局钩子 orm_obj.clean

posted @ 2020-03-05 18:54  赵刚、  阅读(198)  评论(0编辑  收藏  举报