diango基础知识总结 下载 创建项目 启动项目 使用顺序 index 一个项目的结构 diango运行流程 创建一个app Django使用MySQL数据库的流程 ORM 对象关系映射 cookie 装饰器 response session 正则表达式 url的命名和反向解析 MVC MTV request对象的方法 response对象的方法 模板中 过滤器 标签 if 不支持算数运算 csrf 母版和继承 使用admin的步骤 中间件 AJAX form组件

diango基础知识总结
下载
创建项目
启动项目
使用顺序
index
一个项目的结构
diango运行流程
创建一个app
Django使用MySQL数据库的流程
ORM 对象关系映射
cookie
装饰器
response
session
正则表达式
url的命名和反向解析
MVC
MTV
request对象的方法
response对象的方法
模板中
过滤器
标签
if  不支持算数运算
csrf
母版和继承
使用admin的步骤
中间件
AJAX
form组件

  1. 命令行

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

  2. pycharm

创建项目

  1. 命令行

    django-admin startproject 项目名

  2. pycharm

    file _> new project _> django _> 输入路径 _> 选择解释器 _> 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

  2. pycharm

    点绿三角 django 前面是dj

    可以修改配置 可以改IP和端口

使用顺序

settings 静态文件配置

BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))  #文件夹根目录

DEBUG = True   #因为启动出错调试模式 上线后改为Flase,出错不报错,给用户更好的用户体验

ALLOWED_HOSTS = ['*'] #让所有的用户可以访问

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

MIDDLEWARE = [
    # 'django.middleware.csrf.CsrfViewMiddleware',   #提交POST请求注释一个中间件
]




"""
如果使用sqlite3数据库
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.sqlite3', 
        'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
    }
}
"""

"""
#如果使用mysql数据库
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',   #diango的服务器引擎
        'NAME': 'bookmanager',
        'USER': 'root',
        'PASSWORD': '123',
        'HOST': '127.0.0.1',
        'PORT': 3306,
    }
}

#默认使用pymysql模块 替换
import pymysql
pymysql.install_as_MySQLdb()
"""




LANGUAGE_CODE = 'en-us'       #汉语 'zh-hans'  

TIME_ZONE = 'UTC'   #时区:英国的,改为亚洲上海 'Asia/Shanghai'  

STATIC_URL = '/static/'    #静态文件夹的别名,配置静态文件要以/static/为开头


STATICFILES_DIRS = [                  # 路由
    os.path.join(BASE_DIR,'static1'),   # 存放静态文件的路径
    os.path.join(BASE_DIR,'static1'),
]
				 # join(BASE_DIR必须是这个,静态文件夹static1)
					# 加上静态文件的存放路径

models.py 映射关系

写映射关系操作数据库

settings 配置:

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql', #使用mysql数据库引擎
        'NAME': 'day43',		#默认操作的库
        'HOST': '127.0.0.1',	#库所在的服务器地址		
        'PORT': 3306,			#端口
        'USER': 'root',			#用户名
        'PASSWORD': '123',		#密登密码
    }
}


#默认使用pymysql模块 替换  也可以写在day43的__init__.py里
import pymysql
pymysql.install_as_MySQLdb()

创库

用可视化工具创建一个MySQL数据库

创表

class User(models.Model):
    username = models.CharField(max_length=32)  # varchar(32)
    password = models.CharField(max_length=32)  # varchar(32)
    
#类 对象   属性
#表 数据行 字段


python manage.py  makemigrations  # 制作迁移文件 出现在migrations
python manage.py migrate  # 执行SQL语句 同步 
		#terminal里执行命令

△id字段是自动添加的,如果你想要指定自定义主键,只需在其中一个字段中指定 primary_key=True 即可。如果Django发现你已经明确地设置了Field.primary_key,它将不会添加自动ID列。

urls.py 路由

路径 函数转换

==settings配置:

STATICFILES_DIRS = [                  # 路由
    os.path.join(BASE_DIR,'static1'),   # 存放静态文件的路径
    os.path.join(BASE_DIR,'static2'),
]

url(r^'用户输入输入的路径 0.0.0.0:80/index/',不加括号的函数名)

urlpatterns = [ 	
    url(r'^admin/', admin.site.urls),
    url(r'^index/', index),   # 路径和函数的对应关系,
    url(r'^modal/', modal),  
]

views.py 函数

def index(request):  		    # 函数里写处理逻辑,request拿到网络路径,固定写法
    print(request.path_info)	# 打印网络路

import 导入:

导入返回字符串的包HttpResponse,返回html文件的包render,返回执行另一个逻辑的包

from django.shortcuts import HttpResponse,render, redirect 

导入dpp01文件中的创建数据表的类的models.py文件

from app01 import models

return 返回:

return HttpResponse('

index

')

返回字符串

return HttpResponse('<h1>index</h1>')         # 返回字符串

return render(,,)

返回接受到请求的网络路径要渲染的html文件和要传的值

return render(request, 'index.html',{'k1':v1}) 
#返回   (网络路径必添,要渲染的html文件,{别名:要传的值})

return redirecct('路径')

执行另一个逻辑

ORM的操作

写函数来实现增删该查

.all 获取所有的数据

all_publishers = models.Publisher.objects.all() 
#变量 = 文件名.类名.对象.取值方法
# objects.all() 查询出所有的出版社的信息,是一个对象列表

.filter(pk=pk) 获取所一个数据

第一个pk列名,第二个pk为从request中get到的

变量 = models.User.objects.filter(password='dsb')   # 对象列表	
# 用.first取第一个,若无,返回空列表,if 变量;判断时,不会报错,只是不会执行这个语句了
# 用[0]取值时,,若无,取不到值,if 判断时变量,会报错

get 获取所一个数据

变量 = models.User.objects.get(password='dsb')  # 对象 特点 获取不到或者获取到多个都报错

create(name=pub_name) 添加数据

利用类的对象

obj = models.Publisher.objects.create(name=pub_name)

update(name=pub_name) 跟新数据

templates HTML文件

模板

某.html的settings配置

MIDDLEWARE = [
  
    # 'django.middleware.csrf.CsrfViewMiddleware',   #提交POST请求注释一个中间件
  
]

hyml中的样式路径配置

<head>  
    <title>Title</title>
    <link rel="stylesheet" href="/static/plugins/bootstrap-3.3.7-dist/css/bootstrap.min.css">
    <link rel="stylesheet" href="/static/plugins/font-awesome-4.7.0/css/font-awesome.min.css">
    
    <script src="/static/js/jquery.js"></script>
    <script src="/static/plugins/bootstrap-3.3.7-dist/js/bootstrap.js"></script>
</head>

模板语法

△登录

<div class="container">

    <form class="form-signin" method="post" action="" novalidate>
        <h2 class="form-signin-heading">Please sign in</h2>
        <label for="inputEmail" class="sr-only">用户名</label>
        <input type="text" 
               autofocus="">
        <label for="inputPassword" class="sr-only">密码</label>
        <input type="password" >
        <div>{{ error }}</div>
        <div class="checkbox">
            <label>
                <input type="checkbox" value="remember-me"> Remember me
            </label>
        </div>
        <button class="btn btn-lg btn-primary btn-block">登录</button>

    </form>

△查询所有的作者信息

    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()))  # 所关联的所有的对象

△for循环

views.py传过来的参数:
render(request,'pub.html',{'all_publishers':all_publishers}) 
{{ all_publishers }} 

html的for循环:
{% for i in all_publishers  %}

	{{ forloop.counter }}
	{{ i }}
	{{ i.id }}  {{ i.pk }}
	{{ i.name }}
	
{% endfor %}


△if

{% if 条件 %}
	xxx
{% else %}	
	xxxxx
{% endif %}

△form的注意点

  1. form标签的属性 action='提交的地址' method='post' novalidate 取消input标签自带的校验
  2. input标签必须要有name属性 有些标签有value值
  3. 需要有一个button按钮 或者 type='submit'的input

△get 和 post

get : 获取一个页面

1.直接在浏览器的地址栏中输入地址 回车

2.form表单 不指定method

3.a标签

参数: ?k1=v1&k2=v2

获取参数: request.GET.get('k1')

post : 提交数据

form表单  method = 'post'

获取数据: request.POST.get('k1')

static1 渲染

一个项目的结构

day43项目

.idea 配置

pycharm自动帮配的配置,打开别人的diango项目时要先删了此项

app01

方便在一个大的Django项目中,管理实现不同的业务功能

migrations 放表

放和数据库同步的表

admin.py 后台

后台管理:

1、应用注册

2、admin界面汉化

apps.py 元数据

应用程序设置

元数据

models.py

写映射关系操作数据库

它包含了你存储的数据的重要字段和行为

  • 每个模型都是一个Python类,它是django.db.models.Model的子类。
  • 模型的每个属性都代表一个数据库字段。
#类 对象   属性
#表 数据行 字段
class User(models.Model):
    username = models.CharField(max_length=32) #varchar
    password = models.CharField(max_length=32) #varchar

diango基础知识总结
下载
创建项目
启动项目
使用顺序
index
一个项目的结构
diango运行流程
创建一个app
Django使用MySQL数据库的流程
ORM 对象关系映射
cookie
装饰器
response
session
正则表达式
url的命名和反向解析
MVC
MTV
request对象的方法
response对象的方法
模板中
过滤器
标签
if  不支持算数运算
csrf
母版和继承
使用admin的步骤
中间件
AJAX
form组件

tests.py 测试

views.py

写函数逻辑

day43项目包

init.py 自动执行

#默认使用pymysql模块 替换  也可以写在settings.py里
import pymysql
pymysql.install_as_MySQLdb()

settings

静态文件配置

urls.py

路径 函数转换

wsgi.py 网关接口

WSGI(Python Web Server Gateway Intergace)

中文名:python服务器网关接口,python应用于web服务器之间的接口,很少用到,但是最好不要修改其内容

static1

templates

manage.py 命令行接口

应用的命令行接口

将Django project放到sys.path目录中,同时设置DJANGO_SETTINGS_MODULE环境变量为当前project的setting.py文件。

diango运行流程

Django处理一个请求的流程:

  1. 在浏览器的地址栏中输入地址,回车,发了一个GET请求
  2. wsgi模块接收了请求,将请求的相关信息封装成request对象
  3. 根据地址找到对应函数
  4. 执行函数获取到返回结果,wsgi模块将结果返回给浏览器

发请求的途径:

  1. 在浏览器的地址栏中输入地址 get请求
  2. a标签 get请求
  3. form表单 get/post

reqeust

​ reqeust.GET url上携带的参数 ?k1=v1&k2=v2

​ reqeust.POST form表单提交POST请求的参数

​ request.method 请求方式 GET、POST

response

​ HttpResponse('字符串') ——》 返回字符串

​ render(request,'模板的名字',{}) ——》 返回一个页面

​ redirect('地址') ——》 重定向

创建一个app

terminal里执行命令

python manage.py startapp app名称

注册

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

Django使用MySQL数据库的流程

手动创建一个MySQL数据库

配置数据库

ENGINE   MySQL
NAME	数据库的名字
HOST    ip 
PORT    3306
USER    用户名
PASSWORD  密码

在与settings同级目录下的__init__.py中写代码:

import pymysql
pymysql.install_as_MySQLdb()

写models:

form django.db import models 
class Publisher(models.Model):
	name = models.CharField(max_length=32)

执行迁移的命令

python  manage.py  makemigrations  # 检查已经注册的APP下面的models.py的变更情况
python manage.py migrate   # 执行迁移 

ORM 对象关系映射

对应关系:

​ 类 _> 表

​ 对象 _> 数据行(记录)

​ 属性 _> 字段

ORM能做的事情:对数据做修改、对表做修改

常用的字段

AutoField  自增字段
IntegerField  整数
CharField 字符串
DatetimeField  DateField 日期时间
	auto_now:每次修改时修改为当前日期时间。
	auto_now_add:新创建对象时自动添加当前日期时间。
BooleanField  布尔值
TextField   大文本
ImageField  图片
DecimalField   10进制小数

字段参数

null=True   # 数据库中该字段可以为空
blank=True  # 用户输入可以为空
db_column   # 数据库字段的名
default     # 默认值
primary_key  # 主键
db_index    # True 索引
unique      # 唯一约束
verbose_name   # 中文提示
choices        # 让用户选择的数据

建表的参数

    class Meta:
        # 数据库中生成的表名称 默认 app名称 + 下划线 + 类名
        db_table = "person"

        # # admin中显示的表名称
        verbose_name = '个人信息'

        # verbose_name加s
        verbose_name_plural = '所有用户信息'

        # 联合索引
        # index_together = [
        #     ("name", "age"),  # 应为两个存在的字段
        # ]
        #
        # # 联合唯一索引
        unique_together = (("name", "age"),)  # 应为两个存在的字段

ORM的操作

from django.db import models

class Publisher(models.Model):
    name = models.CharField(max_length=32)
    
# 一对多的关系
class Book(models.Model):
    name = models.CharField(max_length=32)
    pub = models.ForeignKey(to='Publisher',on_delete=None) 
    
    def __str__(self):
        return self.name

查询

from app01 import models 

models.Publisher.objects.all()  #查询所有的数据  QuerySet  对象列表 
models.Publisher.objects.get(name='xxx') 
					#查询一条数据  只能查有且唯一的数据
models.Publisher.objects.filter(name='xxx') 
					#查询所有满足条件的数据 对象列表 
    
for book in all_books:
    print(book)
    print(book.id)
    print(book.pk)
    print(book.name)
    print(book.pub)  # 所关联的出版社对象    	对象.外键
    print(book.pub_id)  # 所关联的出版社对象的id   对象.外键_id

新增

obj = models.Publisher.objects.create(name='xxxx')

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

obj = models.Publisher(name='xxxx')
obj.save()  # 保存到数据库

obj = models.Book(name='xxx',pub_id=出版社的对象id)
obj.save()


多对多的新增:
书对作者
book_id = request.POST.getlist('book_id')
# 插入数据
obj = models.Author.objects.create(name=author_name)
obj.books.set(book_id) # 设置多对多的关系

删除

models.Publisher.objects.filter(pk=pk).delete()   # 批量删除
models.Publisher.objects.get(pk=pk).delete()	# 单条数据的删除

更新

models.Book.objects.filter(pk=pk).update(name=book_name,pub_id=pub_id)  # 批量更新

obj = models.Book.objects.filter(pk=1).first()
obj.name = 'xxxx'
obj.pub_id = 2
# book_obj.pub  =  出版社的对象
obj.save()  #保存更新

外键

一对多的关系

class Book(models.Model):
    name = models.CharField(max_length=32)
    pub = models.ForeignKey('Publisher', on_delete=models.CASCADE)
  
 
    """
    on_delete 在2.0版本之后是必填的
    on_delete= 
        models.CASCADE  级联删除
        PROTECT   保护
        SET(1)    
        SET_DEFAULT  设置为默认值设置为某一个值
        SET_NULL   设置为空
        DO_NOTHING 什么都不变
    """
import os

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

django.setup()  # 初始化

from app01 import models

# 基于对象的查询
# 正向查询
book_obj = models.Book.objects.get(pk=3)
# print(book_obj)
# print(book_obj.pub)

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

# related_name='books'
# print(pub_obj.books.all())


# 基于字段的查询
ret = models.Book.objects.filter(pub__name='老男孩出版社')
# print(ret)

# 没有指定related_name  类名小写__字段
ret = models.Publisher.objects.filter(book__name='没有页码的python书')
# 指定related_name  related_name__字段
ret = models.Publisher.objects.filter(books__name='没有页码的python书')

# 指定related_query_name='book'  related_query_name_name__字段
# ret = models.Publisher.objects.filter(book__name='没有页码的python书')
# print(ret)

多对多

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

class Book(models.Model):
	name = models.CharField(max_length=32)
    pub = models.ForeignKey('Pulisher',on_delete=models.DO_NOTHING)

class Author(models.Model):
	name = models.CharField(max_length=32)
	books= models.ManyToManyField(to='Book') 
# 查询
book_obj.pub   # 所关联的对象   book_obj.pub_id  所关联的对象的id

author_obj.books  # 关系管理对象
author_obj.books.all()   # 所关联的所有的书籍对象
# 新增
Book.objects.create(name='xxx',pub=对象)
Book.objects.create(name='xxx',pub_id=对象的ID)

obj= Book(name='xxx',pub_id=对象的ID)
obj.save()

obj = Author.objects.create(name='xxx')
obj.books.set([书籍id,书籍id])
# 删除
Book.objects.filter(pk=pk).delete()  # QuerySet 删除
Author.objects.get(pk=pk).delete()   # 对象 删除
# 编辑
Book.objects.filter(pk=pk).update(name='xxx')

book_obj.name ='xxxx'
book_obj.save()

Author.objects.filter(pk=pk).update(name='xxx')
author_obj.books.set([id,id])
import os

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

django.setup()  # 初始化

from app01 import models

author_obj = models.Author.objects.get(pk=1)

# print(author_obj.books.all())

book_obj = models.Book.objects.get(pk=1)
# print(book_obj.author_set.all())

ret = models.Author.objects.filter(books__name='没有页码的python书')
ret = models.Book.objects.filter(author__name='bigbao')

# print(ret)
# set 设置多对多的关系  [id]   [对象]
# author_obj.books.set([3,])
# author_obj.books.set( models.Book.objects.all()) # [对象,对象]

# add 添加多对多的关系  id   对象
# author_obj.books.add(1,2,3)
# author_obj.books.add(*models.Book.objects.all())  # *[对象,对象]

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


# clear 清除多对多的关系
# author_obj.books.clear()

# create 新增一个所关联的对象 并且和当前的对象设置关系
author_obj.books.create(name='跟和尚学合气道', pub_id=1)

# book_obj.author_set

# 多对一  反向查询 一 ——》 多  关系管理对象
# 关系管理对象.set([对象,对象])
# 关系管理对象.add(对象,对象)

#  外键字段 null=True, 才有remove,clear
# 关系管理对象.remove(对象,对象)
# 关系管理对象.clear()

# 关系管理对象.create()

必知必会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()

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

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

# values()
#  不指定字段 获取所有字段名和值  QuerySet 对象列表  [ {},{} ]
#  指定字段  values('pid','name')  获取指定字段名和值  QuerySet 对象列表  [ {},{} ]
ret = models.Person.objects.all().values()
ret = models.Person.objects.filter(name='alex').values('pid', 'name')

# values_list()
#  不指定字段 获取所有的值  QuerySet 对象列表  [ (),() ]
#  指定字段  values_list('pid','name')  获取指定的值  QuerySet 对象列表  [ (),() ]
ret = models.Person.objects.all().values_list()
ret = models.Person.objects.filter(name='alex').values_list('name', 'pid', )

# order_by  排序 默认升序  -降序  可以多个字段排序
ret = models.Person.objects.all().order_by('age', '-pid')

# reverse  对已经排序的QuerySet做的反转
ret = models.Person.objects.all().order_by('pid').reverse()

# get    获取满足条件的一个的对象  对象
ret = models.Person.objects.get(name='alex')

# first  获取第一个元素   对象  获取不到的时候是none
ret = models.Person.objects.filter(name='xxx').first()

# last  获取最后一个元素   对象  获取不到的时候是none
ret = models.Person.objects.filter(name='xxx').last()

#  count 计数
ret = models.Person.objects.all().filter(age=84).count()

# exists 数据是否存在
ret = models.Person.objects.filter(age=84).exists()

# distinct  去重  数据时完全一样才去重
ret = models.Person.objects.filter(age=84).values('age').distinct()



"""
返回对象列表
all
filter 
exclude 
order_by 
reverse
values   [{}] 
values_list   [()] 
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)  # greater than   where pk > 3
ret = models.Person.objects.filter(pk__gte=3)  # greater than equal   where pk >= 3

ret = models.Person.objects.filter(pk__lt=3)  # less than   where pk < 3
ret = models.Person.objects.filter(pk__lte=3)  # less than equal   where pk <= 3

ret = models.Person.objects.filter(pk__range=[1,3])  # 1 <= pk <= 3
ret = models.Person.objects.filter(pk__in=[1,3,7,10,100])  # 成员判断

ret = models.Person.objects.filter(name__contains='bigbao')  # like   不忽略大小写
ret = models.Person.objects.filter(name__icontains='bigbao')  # like  ignore  忽略大小写

ret = models.Person.objects.filter(name__startswith='b')  # 以什么开头 不忽略大小写
ret = models.Person.objects.filter(name__istartswith='b')  # 以什么开头 忽略大小写

ret = models.Person.objects.filter(name__endswith='o')  # 以什么结尾 不忽略大小写
ret = models.Person.objects.filter(name__iendswith='o')  # 以什么结尾 忽略大小写

ret = models.Person.objects.filter(age__isnull=False)   # 字段是否为空


ret = models.Person.objects.filter(birth__year='2019')   # 按照年份
ret = models.Person.objects.filter(birth__contains='2019-12-19')  # 时间包含


print(ret)

外间的操作

import os

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

django.setup()  # 初始化

from app01 import models

# 基于对象的查询
# 正向查询
book_obj = models.Book.objects.get(pk=3)
# print(book_obj)
# print(book_obj.pub)

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

# related_name='books'
# print(pub_obj.books.all())


# 基于字段的查询
ret = models.Book.objects.filter(pub__name='老男孩出版社')
# print(ret)

# 没有指定related_name  类名小写__字段
ret = models.Publisher.objects.filter(book__name='没有页码的python书')
# 指定related_name  related_name__字段
ret = models.Publisher.objects.filter(books__name='没有页码的python书')

# 指定related_query_name='book'  related_query_name_name__字段
# ret = models.Publisher.objects.filter(book__name='没有页码的python书')
# print(ret)


聚会和分组

import os

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

django.setup()  # 初始化

from app01 import models

from django.db.models import Max, Min, Avg, Sum, Count

ret = models.Book.objects.filter(id__gt=3).aggregate(max=Max('price'), min=Min('price'))

# 统计每一本书的作者个数
ret = models.Book.objects.annotate(Count('author'))  # 按照book进行分组  统计作者的个数

# 统计出每个出版社的最便宜的书的价格
ret = models.Publisher.objects.annotate(Min('book__price')).values()

ret = models.Book.objects.values('pub', 'pub__name').annotate(Min('price'))

# 统计作者的图书的个数

ret = models.Author.objects.annotate(Count('books')).values()

ret = models.Book.objects.values('author').annotate(Count('id'))

# 统计不止一个作者的图书
ret = models.Book.objects.annotate(count=Count('author')).filter(count__gt=1)

# 根据一本图书作者数量的多少对查询集 QuerySet进行排序
ret = models.Book.objects.annotate(count=Count('author')).order_by('-count')

# 查询各个作者出的书的总价格
ret = models.Author.objects.annotate(Sum('books__price')).values()

ret = models.Book.objects.values('author').annotate(Sum('price'))

print(ret)

F

可以拿字段出来对比

import os

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

django.setup()  # 初始化

from app01 import models
from django.db.models import F, Q


# ret = models.Book.objects.filter(sale__gt=F('kucun'))
# ret = models.Book.objects.update(sale=F('sale')*2)


print(ret)

Q

| 或

& 与
import os

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

django.setup()  # 初始化

from app01 import models
from django.db.models import F, Q

ret = models.Book.objects.exclude(pk__lte=3, pk__gte=2)
ret = models.Book.objects.filter(Q(~Q(Q(pk__gt=3) & Q(pk__lt=2))) & Q(name__contains='跟'))

print(ret)

事务

import os

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

django.setup()  # 初始化

from app01 import models

from django.db import transaction

try:
    with transaction.atomic():
        # 一系列的ORM操作
        models.Publisher.objects.create(name='xxx')
        models.Publisher.objects.create(name='xxx')
except Exception as e:
    print(e)

print('xxx')

cookie

定义

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

特点

1.cookie是由服务器进行设置的
2.浏览器保存在本地的
3.下次访问时自动携带对应的cookie

设置

response.set_cookie(key,value)   # Set-Cookie: is_login=1; Path=/
response.set_signed_cookie('is_login','1',salt='xxxx')
#两种操作方式相同,第二种推荐,salt='xxxx',以xxxx来进行加盐
response.set_signed_cookie(key,value,salt='xxxx',max_age=5,path='/')
	#max_age=5,让浏览器记住登录状态的时间最大为五秒,超过五秒清楚is_login

获取

request.COOKIES #  {} 
request.COOKIES[key]# 没有会报错
request.COOKIES.get(key)
request.get_signed_cookie(key,salt='xxxx',default='')
#default='' 默认值设置为空,不然取不到会报错

删除

response.delete_cookie(key)  # 设置键值对的值为空 超时时间为0

装饰器

让装了装饰器的函数的名字不是inner,而是原来的名字

from functools import wraps

def wrapper(func):
    @wraps(func)  # 复制了原来函数的名字和注释
	def inner(request,*arg,**kwargs):
        # 之前
        ret = func(request,*arg,**kwargs)
        # 之后
        return ret 
    return inner

@wrapper  # f1 = wrapper(f1)
def f1(request):
    pass

f1.__name__  #  inner _> f1   #让装了装饰器的函数的名字不是inner,而是原来的名字

response

diango中有三种response

from django.shortcuts import render, redirect, HttpResponse
HttpResponse()
render()
redirect()

session

定义

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

为什么要有session?

  1. cookie保存在浏览器上,不太安全
  2. cookie的大小和个数有限制

设置

request.session[key] = value 
request.session[is.login]=1

获取

request.session[key] #这样取值没有取值会报错
request.session.get(key)

删除

request.session.pop('is_login')
request.session.delete()  #  删除所有的session数据
request.session.flush()   #  删除所有的session数据和cookie

其他

request.session.clear_expired()		#清除过期的session  ?
request.session.set_expiry(value)   #设置session过期的时间

配置

from django.conf import global_settings
#在global_settings中查看全局配置
#在settings中覆盖修改

SESSION_COOKIE_NAME = 'session'   # cookie的名字
SESSION_SAVE_EVERY_REQUEST = True  # 每次请求都更新session
SESSION_EXPIRE_AT_BROWSER_CLOSE = True  # 浏览器关闭session就失效

SESSION_ENGINE = 'django.contrib.sessions.backends.db'
from django.contrib.sessions.backends import db #session在哪储存
# 数据库  缓存  缓存+数据库  文件 加密cookie

正则表达式

^ 开头

$ 结尾

[0-9] 数字

[a-zA-Z] 英文字母

[asd]{4,6}

+(一个或多个)
*(0个或多个)

? (0个或1个)

d 阿拉伯数字

w 匹配字母或数字或下划线或汉字 等价于'[^A-Za-z0-9_]

.(除了换行符之外的任意字符)

url的命名和反向解析

静态路由

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

反向解析ht

模板

{% url 'login' %}   ——》  '/app01/login/'

py文件

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

分组路由

位置传参

url(r'^del_publisher/(d+)/', views.del_publisher,name='del_pub'),
#分组后从url中捕获参数,捕获的参数会按照 位置传参 传递给函数

关键字传参

url(r'^del_publisher/(?P<pk>d+)/', views.del_publisher),
#分组后从url中捕获参数,捕获的参数会按照 关键字传参 传递给函数

反向解析

模板

{% url 'del_pub' '1' %}   ——》  '/app01/del_publisher/1/'

py文件

from django.urls import reverse
reverse('del_pub',args=('1',))   ——》  '/app01/del_publisher/1/'

命令分组 路由

url(r'^del_publisher/(?P<pk>d+)/', views.del_publisher,name='del_pub'),

反向解析

模板

{% url 'del_pub' '1' %}   ——》  '/app01/del_publisher/1/'     位置传参
{% url 'del_pub' pk='1' %}   ——》  '/app01/del_publisher/1/'  关键字传参

py文件

from django.urls import reverse
reverse('del_pub',args=('1',))   ——》  '/app01/del_publisher/1/'    位置传参
reverse('del_pub',kwargs={'pk':'1'})   ——》  '/app01/del_publisher/1/'  关键字传参

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:del_pub' '1' %}
reverse('app01:del_pub',args=('1',)) 

MVC

M: model 模型 与数据库交互

V: view 视图 HTML

C:controller 控制器 流程 和 业务逻辑

MTV

M:model ORM

T:template 模板 HTML

V:view 视图 业务逻辑

Django中的视图

FBV

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

urls.py

  url(r'^add_publisher',add_publisher )

CBV

from django.views import View
class Addpublisher(View):
	def get(self,reuqest,*args,**kwargs)
        # 处理GET请求的逻辑
        self.request
        return  response
    
    def post(self,reuqest,*args,**kwargs)
        # 处理POST请求的逻辑
        return  response

urls.py

  url(r'^add_publisher',Addpublisher.as_view() )

CBV中不同的请求能找到相应函数执行的原因:
继承了View,程序加载的时候,执行View中的Addpublisher.as_view(),
Addpublisher.as_view()定义了一个view函数,返回view,通过反射获取请求方式对应的方法(get/post)。

as_view的流程:

1. 程序加载的时候,执行Addpublisher.as_view():

   定义了一个view函数,返回view

   url(r'^add_publisher',view )

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

   1. 实例化对象  ——》 self
   2. self.request = request
   3. 执行self.dispatch(request, *args, **kwargs)
      1. 判断请求方式是否被允许:
         1. 允许: 通过反射获取请求方式对应的方法(get/post)  ——》 handler
         2. 不允许:self.http_method_not_allowed  ——》 handler
      2. 执行handler,将它的结果返回

加装饰器

FBV

FBV 直接加

@login_required
def publisher(request):

CBV

解决装饰器加同时加在类和函数上时的参数导致的复用性问题:
不加method_decorator,加在类方法上,需要第一个参数需要是self,如果在login_required的inner括号里加上了self,函数便无法用这个装饰器了,所以装饰器加在类上时要借助method_decorator

from django.utils.decorators import method_decorator

登录验证的装饰器
def login_required(func):
    def inner(request, *args, **kwargs):
        # print(request.COOKIES)
        # is_login = request.COOKIES.get('is_login')
        # is_login = request.get_signed_cookie('is_login', salt='xxxx', default='')
        is_login = request.session.get('is_login')
        # print(request.path_info)
        # print(request.get_full_path())
        print(request.META.get('HTTP_ACCEPT'))

        print(is_login)
        if is_login != 1:
            # 没有登录 跳转到登录页面
            url = request.path_info
            return redirect('/login/?url={}'.format(url))
        ret = func(request, *args, **kwargs)

        return ret

        # if is_login == '1':
        #     # 登录
        #     ret = func(request, *args, **kwargs)
        #     return ret
        # else:
        #     url = request.path_info
        #     return redirect('/login/?url={}'.format(url))

    return inner



# 加在方法上
@method_decorator(login_required)
def get(self, request, *args, **kwargs):

# 重写dispatch方法,加在dispatch方法上
@method_decorator(login_required)
def dispatch(self, request, *args, **kwargs):
    ret = super().dispatch(request, *args, **kwargs)
    return ret

#直接找到父类的dispatch方法加上去 ——最简单!推荐!
@method_decorator(login_required,name='dispatch')
class Addpublisher(View)

# 加在类上
@method_decorator(login_required,name='post')
@method_decorator(login_required,name='get')
class Addpublisher(View)

request对象的方法

request.method  # 请求方法 GET POST 
request.GET     # url上携带的参数  {}  
request.POST   # form提交POST请求的参数  {}   编码类型是urlencode 
request.body   # 请求体  b''
request.path_info  # 路径  不包含ip和端口  也不包含参数
request.COOKIES  # cookie的字典 
request.session  # session的数据
request.FILES  # 上传的文件  编码的类型是  enctype="multipart/form-data"
request.META     # 请求头   小写 ——》 大写  HTTP_    - _> _

request.get_full_path()   # 路径  不包含ip和端口  包含参数
request.get_signed_cookie(key)  # 获取加密cookie
request.is_ajax()   # 是否是ajax

response对象的方法

HttpResponse('xxxx')  # 返回字符串   Content-Type: text/html; charset=utf-8
render(request,'模板的路径',{})   # 返回一个页面
redirect('路径')   # 重定向  状态码301 302  响应头 Location:路径

from django.http.response import JsonResponse

模板中

变量 {{ 变量名 }}

通过(.)取相应的内容

.key > .属性 .方法 > .索引

过滤器

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

{{ kong | default:'没有传参' }}

filter

{{ 变量|filter:参数 }}

default add length slice join first last lower upper title truncatechars truncatewords

date:"Y-m-d H:i:s" safe

USE_L10N = False
DATETIME_FORMAT = 'Y-m-d H:i:s'

标签

{% %}

for

{%  for i in list %}

	{{ i }}

{% endfor %}

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

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

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

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

forloop.first 是否是第一次循环

forloop.last 是否是最后一次循环

forloop.parentloop 当前循环的外层循环 {}

{% for i in list  %}
	{{ forloop }}
	{{ i }}
	
{% empty %}
	空空如也
{% endfor %}

if 不支持算数运算

{% if  条件  %}
	x
{% elif  条件1  %}
	xx
{% else %}
	xxx
{% endif %}

注意点:

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

csrf

{% csrf_token %}  #  form表单中有一个隐藏的input标签  name=‘csrfmiddlewaretoken’

母版和继承

母版:

​ 模板,提取出多个页面公共部分放在一个母版中,定义上多个block块,让子页面重新复写。

继承:

  1. {% extends ‘母版的名字’ %}
    2. 重写block块。

注意点:

1. {% extends ‘母版的名字’  %}  母版名字 的引号好带上   不带会当做变量
  1. {% extends ‘母版的名字’ %} 上不要写内容

    1. 要替换母版的内容都写在block块中

    2. 定义多个block块, css,js

组件:

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

{% include 'nav.html ' %}

静态文件的使用:

{% load static %}
"{% static '静态文件的相对路径' %}"

母版和组件的继承和引用怎么用?

使用admin的步骤

  1. 创建超级用户

    python manage.py createsuperuser

  2. 注册model

    在app下的admin.py中注册

    from django.contrib import admin
    from app01 import models
    # Register your models here.
    admin.site.register(models.Person)
    
  3. 访问网站登录操作

中间件

process_request(self,request)

参数:

​ request 请求的对象,和视图中的request是同一个

执行时间:视图函数之前

执行顺序:

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

返回值

​ None : 正常流程

​ HttpReponse: 当前中间件之后的中间件的process_request方法、路由匹配、视图也不执行,直接执行当前中间件的process_response方法

process_response(self, request, response)

参数:

​ request 请求的对象,和视图中的request是同一个

​ response 返回的响应对象

执行时间:视图函数之后

执行顺序:

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

返回值

​ HttpReponse: 必须返回响应对象

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

参数:

​ request 请求的对象,和视图中的request是同一个

​ view_func 视图函数

​ view_args 视图函数的位置参数

​ view_kwargs 视图函数的关键字参数

执行时间:路由匹配之后,视图函数之前

执行顺序:

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

返回值

​ None 正常流程

​ HttpReponse: 当前中间件之后的process_view、视图不执行,执行最后一个中间的process_response

process_exception(self, request, exception)

参数:

​ request 请求的对象,和视图中的request是同一个

​ exception 错误对象

执行时间(触发条件):视图层面有错误才执行

执行顺序:

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

返回值

​ None 当前中间没有处理异常,交由下一个中间件处理异常,所有的中间件都没有处理,Django处理错误

​ HttpReponse: 当前中间处理好异常,之后执行最后一个中间件的process_response方法

pocess_template_response(self,request,response)

参数:

​ request 请求的对象,和视图中的request是同一个

​ response 返回的响应对象

执行时间:视图必须返回一个template_response对象

执行顺序:

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

返回值

​ HttpReponse: 必须返回响应对象

response.template_name = 'index1.html'  # 改模板
response.context_data # 改变量

diango基础知识总结
下载
创建项目
启动项目
使用顺序
index
一个项目的结构
diango运行流程
创建一个app
Django使用MySQL数据库的流程
ORM 对象关系映射
cookie
装饰器
response
session
正则表达式
url的命名和反向解析
MVC
MTV
request对象的方法
response对象的方法
模板中
过滤器
标签
if  不支持算数运算
csrf
母版和继承
使用admin的步骤
中间件
AJAX
form组件

1. 简介目录
![img](file:///C:UsersacerAppDataRoamingTencentQQTemp%W@GJ$ACOF(TYDYECOKVDYB.png)https://www.cnblogs.com/maple-shaw/p/9029086.html

2. 路由系统
![img](file:///C:UsersacerAppDataRoamingTencentQQTemp%W@GJ$ACOF(TYDYECOKVDYB.png)https://www.cnblogs.com/maple-shaw/articles/9282718.html

3. 视图
![img](file:///C:UsersacerAppDataRoamingTencentQQTemp%W@GJ$ACOF(TYDYECOKVDYB.png)https://www.cnblogs.com/maple-shaw/articles/9285269.html

4. 模板
![img](file:///C:UsersacerAppDataRoamingTencentQQTemp%W@GJ$ACOF(TYDYECOKVDYB.png)https://www.cnblogs.com/maple-shaw/articles/9333821.html

5.ORM
字段和参数:![img](file:///C:UsersacerAppDataRoamingTencentQQTemp%W@GJ$ACOF(TYDYECOKVDYB.png)https://www.cnblogs.com/maple-shaw/articles/9323320.html
查询操作:![img](file:///C:UsersacerAppDataRoamingTencentQQTemp%W@GJ$ACOF(TYDYECOKVDYB.png)https://www.cnblogs.com/maple-shaw/articles/9403501.html
练习题:![img](file:///C:UsersacerAppDataRoamingTencentQQTemp%W@GJ$ACOF(TYDYECOKVDYB.png)https://www.cnblogs.com/maple-shaw/articles/9414626.html

6. cookie和session
![img](file:///C:UsersacerAppDataRoamingTencentQQTemp%W@GJ$ACOF(TYDYECOKVDYB.png)https://www.cnblogs.com/maple-shaw/articles/9502602.html

7.中间件
![img](file:///C:UsersacerAppDataRoamingTencentQQTemp%W@GJ$ACOF(TYDYECOKVDYB.png)https://www.cnblogs.com/maple-shaw/articles/9333824.html

8. ajax
![img](file:///C:UsersacerAppDataRoamingTencentQQTemp%W@GJ$ACOF(TYDYECOKVDYB.png)https://www.cnblogs.com/maple-shaw/articles/9524153.html

9. form组件
![img](file:///C:UsersacerAppDataRoamingTencentQQTemp%W@GJ$ACOF(TYDYECOKVDYB.png)https://www.cnblogs.com/maple-shaw/articles/9537309.html

AJAX

js技术,发送请求的一种方式.

特点:

  1. 异步
  2. 传输的数据量小
  3. 局部刷新

发请求的途径:

  1. form表单发请求 指定method GET/POST
    1. action 地址 method enctype
    2. input select option 标签要有name属性,有的还需要有value
    3. 有button按钮或者type='submit'的input框
  2. 直接在地址栏中输入地址 回车 get
  3. a标签 get
  4. ajax

发ajax请求的写法:

jQuery:

$.ajax({
    url: '/test/',   //  url路径
    type: 'post',    // 请求方式
    data: {          // 请求数据
        name: 'alex',
        age: 84,
        hobby: JSON.stringify(['吐口水', 'TESA', '篮球', '毒鸡汤']),
    },
    success: function (res) {   // 响应成功的回调函数
        console.log(res);
        console.log(res.status);
        console.log(typeof(res))
    },
    error:function (res) {		// 响应失败的回调函数
        console.log(res)

    }
})

上传文件

$('#b1').click(function () {

        var form_obj = new FormData();  // enctype="multipart/form-data"
        form_obj.append('name', 'alex')
        form_obj.append('f1', $('#f1')[0].files[0])

        $.ajax({
            url: '/upload/',
            type: 'post',
            data: form_obj,
            processData: false, // 不需要处理编码方式
            contentType: false, // 不需要处理contentType请求头
            success:function (res) {  //  响应成功的回调函数  res _> 返回的响应体
                alert(res)
            }

        })
    })

CSRF中间件

  1. process_request方法:

    从cookie中获取csrftoken的值,放到request.META中

  2. process_view方法:

    1. 判断视图是否使用csrf_exempt装饰器,使用了就不校验
    2. 判断请求方式是否是'GET', 'HEAD', 'OPTIONS', 'TRACE',如果是,也不校验
    3. 进行校验:
      1. csrf_token = request.META.get('CSRF_COOKIE') # cookie中获取csrftoken的值
    4. 请求方式是POST
      1. request_csrf_token = request.POST.get('csrfmiddlewaretoken', '')
      2. 获取不到,从头中获取x-csrftoken的值 = >request_csrf_token
      3. 进行比较csrf_token request_csrf_token的值:
        1. 对比成功 接收请求
        2. 对比不成功 拒绝请求

ajax通过Django的csrf校验

前提:

有csrftoken的cookie:

  1. {% csrf_token %}

  2. from django.views.decorators.csrf ensure_csrf_cookie
    

方式一:

给data中添加csrfmiddlewaretoken的键值对

方式二:

给headers添加x-csrftoken的键值对

headers: { 
'x-csrftoken': $('[name="csrfmiddlewaretoken"]').val()},

方式三:

导入文件

csrf相关的装饰器

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

csrf_exempt   豁免csrf的校验   CBV需要加在dispatch方法上才生效
csrf_protect  强制校验
ensure_csrf_cookie  添加csrftoken的cookie

form组件

定义:

from django import forms

class RegForm(forms.Form):
    user = forms.CharField(label='用户名')
    pwd = forms.CharField(label='密码',widget=forms.PasswordInput)

使用:

视图函数:

def reg2(request):
    form_obj = RegForm()
    if request.method == 'POST':
        form_obj = RegForm(request.POST)
        if form_obj.is_valid():
            # 校验成功
            # form_obj.cleaned_data # 清洗后的数据
            return HttpResponse('注册成功')


    return render(request, 'reg2.html', {'form_obj': form_obj})

模板:

{{ form_obj.as_p }}   _>       生成所有字段的input框

{{ form_obj.user }}         _> 某个字段的input框
{{ form_obj.user.label }}   _> 某个字段的中文提示
{{ form_obj.user.id_for_label }}   _> 某个字段的input框的ID


{{ form_obj.errors }}   _>  所有的错误
{{ form_obj.user.errors }}  _>  某个字段的所有错误
{{ form_obj.user.errors.0 }}  _>  某个字段的第一个错误

常用的字段

CharField  
ChoiceField
MultipleChoiceField  

字段的参数

initial  初始值
required  是否必填
disabled  是否禁用
label 	  中文提示
initial   默认值
min_length  最小长度
error_messages   错误信息
choices   可选择的数据

校验

  1. 自带的校验

  2. 自定义校验规则

    1. 写函数

      from django.core.exceptions import ValidationError
      
      
      def check_name(value):
          # 自定义校验规则
          # 如果校验合格 什么都不做
          # 校验不合格   抛出异常
          if 'alex' in value:
              raise ValidationError('不能包含alex,非法字符')
              
      
  3. 使用内置的校验器

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

局部钩子和全局钩子

def clean_user(self):
    # 局部钩子
    # 校验成功  返回当前字段的值
    # 校验不成功  抛出异常
    if 'alex' in self.cleaned_data.get('user'):
        raise ValidationError('不能包含alex,非法字符')
    return self.cleaned_data.get('user')

def clean(self):
    # 全局钩子
    # 校验成功  返回所有字段的值 self.cleaned_data
    # 校验不成功  抛出异常
    pwd = self.cleaned_data.get('pwd')
    re_pwd = self.cleaned_data.get('re_pwd')
    if pwd == re_pwd:
        return self.cleaned_data
    else:
        self.add_error('re_pwd','两次密码不一致!!!')
        raise ValidationError('两次密码不一致')