1. Django的MTV模式:
Model(模型):负责业务对象与数据库的对象(ORM)
Template(模板):负责如何把页面展示个用户
View(视图):负责业务逻辑,并在适当的时候调用Model和Template
此外,Django还有一个url分发器,它的作用是将一个个URL的页面请求分发给不同的view处理,view再调用相应的Model和Template
2. Django工程
1)创建一个django工程:djando-admin.py startproject mysite
manage.py Django项目里面的工具,通过它可以调用django.shell和数据库等
settings.oy 包含了项目的默认设置,包括数据库信息,调试标志以及其他一些工作的变量
urls.py 负责把URL模式映射到应用程序
2)在mysite目录下创建blog应用:python manage.py startapp blog
3)启动djando项目:python manage.py runserver 8080
3. settings配置文件
TEMPLATES下的
'DIRS': [os.path.join(BASE_DIR, 'templates')]
做了一个路径拼接
4. Django URL(路由系统)
本质上是url模式与视图函数之间的对应
urlpatterns = [
path(正则表达式, views视图函数, 参数, 别名),
]
正则表达式:一个正则表达式字符串
views视图函数:一个可调用对象,通常为一个视图函数或一个指定视图函数路径的字符串
参数:可选的要传递给视图函数的默认参数(字典形式)
别名:一个可选的name参数
from django.contrib import admin
from django.urls import path
from blog import views
from django.conf.urls import url,include
urlpatterns = [
path('admin/', admin.site.urls),
path("current_time", views.current_time),
path("user_info", views.user_info),
# 按照位置接收参数
url(r"^articles/([0-9]{4})/$", views.year_archive),
# 按照参数名接收参数
url(r"^articles/(?P<year>[0-9]{4})/(?P<month>[0-9]{2})/$", views.month_archive),
# 参数三
url(r"^articles/(?P<year>[0-9]{4})/(?P<month>[0-9]{2})/$", views.month_archive,
{"year": "1990", "month": "8"}),
# 参数四
url(r"^articles/(?P<year>[0-9]{4})/(?P<month>[0-9]{2})/$", views.month_archive,
{"year": "1990", "month": "8"}, name="articles"),
# url映射分发
url(r"^blog/", include('blog.urls'))
]
5. Django视图函数
http请求中产生两个核心对象:
http请求:HttpRequest对象
Http响应:HttpResponse对象
所在位置:django.http
1) HttpRequest对象的属性:
path: 请求页面的全路径,不包括域名
method:请求中使用的http方法的字符串表示。全大写表示
if request.method == "GET":
pass
elseif request.method == "POST":
pass
GET:包含所有HTTP GET参数的类字典对象
POST:包含所有HTTP POST参数的类字典对象
COOKIES:包含所有cookies的标准Python字典对象;keys和values都是字符串
FILES:包含所有上传文件的类字典对象;FILES中的每个key都是<input type="file" name=""/>标签中
name属性的值,FILES中的每一个value同时也是一个标准的python字典对象,包含下面三个Keys:
filename:上传文件名,用字符串表示
content_type:上传文件的Content Type
content:上传文件的原始内容
user:是一个django.contrib.auth.models.User对象,代表当前登录的用户。如果访问用户当前没有登录,user将被初始化为django.contrib.auth.models.AnonymousUser的实例。你可以通过user的is_authenticated()方法来辨别用户是否登录:
if request.user.is_authenticated(): 只有激活Django中的AuthenticationMiddleware时该属性才可用
2)HttpResponse对象:
每个view请求处理方法必须返回一个HttpResponse对象。HttpResponse类在django.http.HttpResponse
在HttpResponse对象上扩展的常用方法:
页面渲染:render(), render_to_response(),
页面跳转:redirect()
locals():可以直接将函数中所有的变量传给模板
6. 模板语言
html+逻辑控制语言
1){{ 变量 }}
2)万能的句点号: .
列表、字典、属性、类都可以用.来取到
3){% if %}
{% if 1%}
<p>Hello World</p>
{% elif obj %}
<p>Buy</p>
{% endif %}
4){% for %}
{% for i in obj %}
<p>{{ i }}</p>
{% endfor %}
{% for i in obj %}
<p>{{ forloop.counter0 }}:{{ i }}</p>
{% endfor %}
5)过滤器(filter)的使用
{{ ship_date|date:"FJ,Y"}},ship_date变量传给date过滤器,date过滤器通过使用“FJ,Y”这几个参数来格式化日期数据。“|”
{{ obj|upper }}
{{ obj|lower }}
add:给变量加上相应的值
addslashes:给变量中的引号前加上斜线
capfirst:首字母大写
cut:从字符串中移除指定的字符
date:格式化日期字符串
default:如果值是False,就替换成设置的默认值,否则就使用本来的值
default_if_none:如果值是None就替换成设置的默认值,否则就使用本来的值
filesizeformat:文件大小
6)告知浏览器可以渲染(可能经常用到,推荐第二种safe方法)
{# value6='<a href="#">跳转</a>' #}
{% autoescape off %}
{{ value6 }}
{% endautoescape %}
{{ obj|safe}} 也可以达到相同的效果
7){% csrf_token %}(加在form标签最后一行)
用于生成csrf_token的标签,用于防止跨站攻击验证
8){% load%}:加载标签库
9){% url %}:引用路由配置的地址
<form action={% url 别名 %}>
10){% with %}:用更简单的变量名替代复杂的变量名
11){% verbatim %}:禁止render
7. 自定义模板标签
a. 在app中创建templatetags模块(必须)
b. 创建任意.py文件,如add100.py
from django import template
from django.utils.safestring import mark_safe
register = template.Library() # register的是固定变量名,不能改变
@register.simple_tag
def my_add100(v1):
return v1 + 100
@register.simple_tag
def my_input(id, arg):
result = "<input type='text' id='%s' class='%s' />" % (id, arg)
return mark_safe(result)
c. 在自定义simple_tag的html文件中导入之前创建的add100.py文件名
{% load add100 %}
d. 使用simple_tag
{% my_add100 3 %}
{% my_input 'id_username' 'hide' %}
8. django模板
在模板中将变化的部分改为(以下的block名为“content”):
{% block content %}
{% endblock %}
然后在继承的网页中引入模板
{% extends "base.html" %}
{% block content %}
<div class="content">订单</div>
{% endblock %}
9. djando ORM
1)创建表
from django.db import models
# Create your models here.
class UserInfo(models.Model):
username = models.CharField(max_length=64)
gender = models.CharField(max_length=64)
email = models.CharField(max_length=64)
age = models.IntegerField()
publisher = models.ForeignKey("Publisher") # 一对多关系
# 接受对象
author = models.ManyToManyField("Author")
def __str__(self):
return self.title
创建类之后,输入如下代码创建表
python manage.py makemigrations
python manage.py migrate
2)添加对象
create方式一:
Book.objects.create(
title="A",
price=1,
color="green",
publisher_id=4,
# 因为外键关系是一对多,publisher只能对应一个对象
)
create方式二(推荐使用这种方式):
Book.objects.create(**{"title":"A", "price":1, "color":"green"})
save方式一:
book=Book(title="B", price=10, color="grey")
book.save()
save方式二:
book=Book()
book.title="C"
book.price=100
book.color="yellow"
book.save()
3)删(delete)
Book.objects.filter(id=1).delete()
4)改(update和save)
save方式:
book = Book.objects.get(title="A")
book.price = 30
book.save()
update方式(这种方式效率更高):
Book.objects.filter(title="C").update(price=25) # 不能用get方法
注意:update方式不能使用get的原因是:update是QuerySet对象的方法,get返回的是一个model对象,它没有update方法,而filter返回的是一个QuerySet对象
注意,这里因为update返回的是一个整型,所以没法用query属性;对于每次创建一个对象,想显示对应的raw sql,需要在settings加上日志记录部分:
LOGGING={
'version':1,
'disable_existing_loggers':False,
'handlers':{
'console':{
'level':'DEBUG',
'class':'logging.StreamHandler',
},
},
'loggers':{
'django.db.backends':{
'handlers':['console'],
'propagate':True,
'level':'DEGUG',
},
}
}
5)查(filter, value等)
查询API:
(1)filter(**kwargs):它包含了与所给筛选条件相匹配的对象
(2)all():查询所有结果
(3)get(**kwargs):返回与所给筛选条件相匹配的对象,返回结果有且只有一个,如果符合筛选条件的对象超过一个或者没有都会抛出错误。
下面的方法都是对查询的结果再进行处理:比如objects.filter.values()
(4)values(*field):返回一个ValueQuerySet--一个特殊的QuerySet,运行后得到的并不是一系列model的实例化对象,而是一个可迭代的字典序列
(5)exclude(**kwargs):它包含了与所给筛选条件不匹配的对象
(6)order_by(*field):对查询结果排序,倒序:order_by("-id")
(7)reverse():对查询结果反向排序
(8)distinct():从返回结果中剔除重复记录
(9)values_list(*field):它与values()非常相似,它返回的是一个元祖序列,values返回的是一个字典序列
(10)count():返回数据库中匹配查询(QuerySet)的对象数量
(11)first():返回第一个条记录
(12)last():返回最后一条记录
(13)exists():如果QuerySet包含数据,就返回True,否则返回False
惰性机制:Book.objects.all()或者filter()等都只是返回了一个QuerySet(查询结果集对象),他并不会马上执行sql,而是当调用QuerySet的时候才执行。
QuerySet特点:可迭代的、可切片
objs = models.Book.objects.all()
for obj in objs:
print(obj)
print(objs[1:4])
print(objs[::-1])
正向查询:
book=models.Book.objects.filter(id-2)[0]
authors=models.Author.objects.filter(id_gt=2)
book.author.add(*authors)
book.author.remove(*author)
obj.book_set.values("title").distinct()
反向查询:
author=models.Author.objects.filter(id=3)[0]
books=models.Book.objects.filter(id_gt=2)
author.book_set.add(*books)
单表条件查询(注:是双下划线):
models.TB.objects.filter(id__lt=10, id__gt=1) # 获取id大于1且小于10的值
models.TB.objects.filter(id__in=[11, 22, 33]) # 获取id等于11、22、33的数据
models.TB.objects.exclude(id__in=[11, 22, 33]) # not in
models.TB.objects.filter(name__contains="Ti") # 获取名字中包含“Ti”的数据
models.TB.objects.filter(name__icontains="Ti) # icontains大小写不敏感
models.TB.objects.filter(id__range=[1, 10]) # 范围between a and b
startswith, istartswith, endswith, iendswith
聚合查询和分组查询
(1)aggregate(*args, **kwargs)
通过对QuerySet进行计算,返回一个聚合值得字典。aggregate()中每一个参数都指定一个包含在字典中的返回值。即在查询集上生成聚合。
from django.test import TestCase
# Create your tests here.
from django.db.models import Avg,Min,Sum,Max
# aggregate(*args, **kwargs)
# 计算所有书的平均价格
Book.objects.all().aggregate(Avg("price"))
# aggregate()子句的参数描述了我们想要计算的聚合值
# 如果为聚合值制定一个名称,可以向聚合子句提供它:
Book.objects.aggregate(average__price=Avg('price'))
Book.objects.filter(title="A").aggregate(Avg("price"), Max("price"), Min("price"))
# ----------------------------------------------------------------------
# annotate(*args, **kwargs) 分组
# 可以通过计算查询结果中每一个对象所关联的对象集合,从而得出总计值(也可以是平均值或总和),即为查询集的每一项生成聚合。
Book.objects.filter(author__name='Bob').aggregate(Sum('price'))
# 查询各个作者的书的总价格,这里就涉及到分组了,分组条件是authors__name
Book.objects.values("authors__name").annotate(Sum('price'))
# 查询各个出版社最便宜的书价是多少
Book.objects.values("publisher_name").annotate(Min('price'))
F查询和Q查询:
仅仅靠单一的关键字参数查询已经很难满足查询要求。
# F使用查询条件的值,专门取对象中某列值的操作(只能操作数值)
from django.db.models import F
models.Book.objects.all().update(num=F('num')+1)
# Q构建搜索条件
from django.db.models import Q
# 1 Q对象(django.db.models.Q)可以对关键字参数进行封装,从而更好地应用多个查询
q1 = models.Book.objects.filter(Q(title__startswith='P')).all()
# 2 可以组合使用&,|操作符,当一个操作符是用于两个Q的对象,它产生一个新的对象
obj = models.Book.objects.filter(Q(id=3) | Q(title='python'))
# 3 Q对象可以用~操作符放在前面表示否定,也可允许否定与不否定形式的组合
models.Book.objects.filter(Q(title__startswith='p') | ~Q(author="A"))
# 4 Q对象可以与关键字参数查询一起使用,不过一定要把Q对象放在关键字参数查询的前面
models.Book.objects.filter(Q(price__gt=50)&(Q(id=3)|Q(title='php')),
color='yellow,')
6)创建多种关系
创建一对多关系:
publisher = models.ForeignKey("Publish")
创建多对多关系(会创建第三张表):
author = models.ManyToManyField("Author")
模型之间的三种关系:一对一,一对多,多对多
一对一:实质就是在主外键(author_id就是foreign key)的关系基础上,给外键加了一个UNIQUE=True的属性;
一对多:就是主外键关系(foreign key)
(1)models.Book.objects.create(title="Python",price=12,publish_id=2)
(2)(推荐)models.Book.objects.create(title="Python",price=12,publish=obj)
多对多:彼此一对多,自动创建第三张表(当然也可以自己创建第三张表)
自己创建第三张表
class Book2Author(models.Model):
author=models.ForeignKey("Author")
book=models.ForeignKey("Book")
# 创建联合唯一索引
class Meta:
unique_together=["author","book"]
8)models字段
AutoField(Field) int自增列,必须填入参数primary_key=True
BigAutoField(Field) bigint自增列
IntegerField(Field) 整数列
BooleanField(field) 布尔值类型
NullBooleanField(Field) 可以为空的布尔值
CharField(Field) 字符类型,必须提供max_Length参数,max_length表示字符长度
TextField(Field) 文本类型
IPAdressField(Field) 字符串类型,Django Admin以及ModelForm中提供验证IPV4机制
URLField(CharField) 字符串类型,Django Admin以及ModelForm中提供验证URL
FileField(Field) 字符串,路径保存在数据库,文件上传到指定目录;
参数:
upload_to="" :上传文件的保存路径
storage = None:存储组件,默认django.core.files.storage.FileSystemStorage
ImageField(FileField):字符串,路径保存在数据库,文件上传到指定目录
参数:
upload_to="" :上传文件的保存路径
storage = None:存储组件,默认django.core.files.storage.FileSystemStorage
width_field = None:上传图片的高度保存的数据库字段名(字符串)
height_field = None:上传图片的宽度保存的数据库字段名
DateTimeField(DateField):日期+时间格式 YYYY-MM-DD HH:MM:SS
FLoatField(Field):浮点型
DecimalField(Field): 10进制小数
BinaryField(Field):二进制整数
9)参数:
null 数据库中字段是否可以为空
db_column 数据库中字段的列名
default 数据库中字段的默认值
primary_key 数据库中字段是否为主键
db_index 数据库中字段是否可以建立索引
unique 数据库中字段是否可以建立唯一索引
unique_for_date 数据库中字段【日期】部分是否可以建立唯一索引
unique_for_month 数据库中字段【月】部分是否可以建立唯一索引
unique_for_year 数据库中字段【年】部分是否可以建立唯一索引
verbose_name Admin中显示的字段名称
blank Admin中是否允许用户输入为空
editable Admin中是否可以编辑
help_text Admin中该字段的提示信息
choices Admin中显示选择框的内容,用不变动的数据放在内存中从而避免跨表操作,例:city = models.IntegerField(choices=[(0, '邯郸'),(1, "邢台"),], default=1)
error_messages 自定义错误信息(字典类型),从而定制想要显示的错误信息。字典键:null, blank, invalid, invalid_choice, unique, unique_for_date,例:{'null': '不能为空','invalid': '格式错误'}
validators 自定义错误验证(列表类型),从而定制想要的验证规则
from django.core.validators import RegexValidator
from django.core.validators import EmailValidator, URLValidator, DecimalValidator,\
MaxLengthValidator, MinLengthValidator, MaxValueValidator, MinValueValidator
test = models.CharField(
max_length = 32,
error_messsage={
'c1': "自定制错误1",
'c2': "自定制错误2",
'c3': "自定制错误3",
},
validators={
RegexValidator(regex='root_\d+', message='错误了', code='c1'),
RegexValidator(regex='root_[abc]\d+', message='错误了', code='c1'),
EmailValidator(message='邮箱验证错误了', code='c3')
}
)
10. Admin简介
Django admin是django自带的一个后台app,提供了后台的管理功能
1)认识ModelAdmin
管理界面的定制类,如需扩展特定的model界面须从该类继承
2)注册model类到admin的两种方式:
(1)使用register方法
(2)使用register的装饰器
3)掌握一些常用的设置技巧
list_display:指定要显示的字段
search_fields:指定搜索的字段
list_filter:指定列表过滤器
ordering:指定排序字段
4)为项目后台创建超级管理员:python manage.py createsuperuser
from django.contrib import admin
# Register your models here.
from blog.models import *
class MyAdmin(admin.ModelAdmin):
# 用以展示数据
list_display = ('username', 'gender', 'email')
# 指定搜索字段
search_fields = ("username")
# 指定列表过滤器
list_filter = ("gender")
# 指定排序字段
ordering = ("-username")
# 隐藏字段的设置
fieldsets = (
(None, {'fields': ('username', "gender")}),
("Advanced options", {'classes':('collapse',),
'fields':('email', )
})
)
admin.site.register(UserInfo, MyAdmin)
11. 基于mysql的数据库连接
1)在app应用下的__init__.py文件下写入
import pymysql
pymysql.install_as_MySQLdb()
2)在settings.py文件中加入mysql的配置
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': "ORM",
"HOST": "127.0.0.1",
"PORT": "3306",
"USER": "root",
"PASSWORD": "root",
}
}
12. Ajax的介绍
AJAX(Asynchronous Javascript And XML)就是“异步Javascript和XML”,即使用Javascript语言与服务器进行异步交互,传输的数据为XML。当服务器响应时,不用刷新整个浏览器页面,而是可以局部刷新
1)优点:
Ajax使用Javascript技术向服务器发送异步请求;
Ajax无须刷新整个页面;
因为服务器相应内容不再是整个页面,而是页面中的局部,所以Ajax性能高;
2)缺点
Ajax并不适合所有场景,很多时候还是要使用同步交互
Ajax虽然提高了用户体验,但无形中向服务器发送的请求次数增多了,导致服务器压力增大;
因为Ajax是在浏览器中使用Javascript技术完成的,所以还需要处理浏览器兼容性问题;
3)四步操作
创建核心对象
使用核心对象打开与服务器的连接
发送请求
注册监听,监听服务器响应
4)XMLHTTPRequest
open(请求方式,URL,是否异步)
send(请求体)
onreadystatechange,指定监听函数,它会在xmlHttp对象的状态发生变化时被调用
readyState,当xmlHttp对象的状态,其中4状态表示服务器响应结束
status:服务器相应的状态码,只有服务器响应结束时才有,200表示响应成功
responseText:获取服务器的响应体
13. jQuery使用ajax
两种方式:
$.ajax("url",{})
$.ajax({})
请求数据:data,processData,contentType,traditional
data:当前ajax请求要携带的数据,是一个json的object对象,ajax方法就会默认把它编码成某种格式(urlencoded:?a=1&b=2)发送给服务端;此外,ajax默认以get方式发送请求
processData:声明当前的data数据是否进行转码或预处理,默认为true,即预处理;if为false,那么对data:{a:1, b:2}会调用son对象的toString()方法,最后得到一个[object, object]形式的结果
contentType:默认值为"application/x-www-form-urlencoded"。发送信息至服务器时内容编码类型。用来指明当前请求的数据编码格式;urlencoded:?a=1&b=2;如果想以其它方式提交数据,比如contentType:"application/json",即向服务器发送一个json字符串;
traditional:一般是我们的data数据有数组时会用到
案例一
function Test2(){
$.ajax({
url:"/jquery_post",
type:"POST",
data:{a:1, b:[2,3,4]},
processData:false,
contentType:"application/json",
traditional:true,
})
}
dataType:预期服务器返回的数据类型,服务器端返回的数据会根据这个值解析后,传递给回调函数。默认不需要显性指定这个属性,ajax会根据服务器返回的contentType来进行转换:比如我们的服务器相应的contentType为json格式,这时ajax方法就会对相应的内容进行一个json格式的转换,if转换成功,我们在success的回调函数里就会得到一个json格式的对象;转换失败就会触发error这个回调函数。如果我们明确地指定目标类型,就可以使用dataType。比如服务器响应(Response Headers)的contentType是json格式,但我们希望得到的是json字符串,那就可以把dataType: text,这样ajax方法就不会把返回的数据进行json格式的转换。
14. JSON
JSON是一种轻量级的数据交换格式
JSON是用字符串来表示Javascript对象,Javascript可以执行这个字符串,得到一个Javascript对象
json就是js对象的一种表现形式(字符串的形式)
1)python与json类型转换时的对应
python json
dict object
list,tuple array
str,unicode string
int,long,float number
True true
False false
None null
2)ajax中执行的函数
beforeSend 前置处理,发送之前的函数
success 成功执行后的函数
error 发送错误后执行的函数
complete 不管成功与否都会执行的函数
function testData(){
$.ajax('ajax_get',{
beforeSend: function(jqXHR, settings){
console.log(arguments);
console.log('beforeSend');
jqXHR.setRequestHeader('test', 'haha');
jqXHR.testData = {a:1, b:2};
},
error: function(){
},
success: function(data){
console.log(data);
},
complete: function(xhr){
console.log(xhr);
console.log(xhr.testData)
}
});
}
状态码:
statusCode:{
'403': function(jqXHR, textStatus, err){
console.log(arguments);
console.log('status code 403');
console.log("ahha403");
},
"400": function(){
console.log('status code 400');
console.log("hhh400")
}
}
15. 同源策略机制
所谓同源是指,域名,协议,端口相同。不同源的客户端脚本(javascript、ActionScript)在没明确授权的情况下,不能读写对象的资源。
跨域请求数据的解决方式:
<script src="http://127.0.0.1:8001/jquery.get/"></script>
16. JSONP
以下为JSONP的一个简单例子:创建一个回调函数,然后在远程服务上调用这个函数并且将JSON数据作为参数传递,完成回调
<script>
function fun1(arg){
alert("hello" + arg);
}
</script>
<script src="http://127.0.0.1:8001/get_byjsonp/"></script>
def get_byjsonp(req):
print("Hello JSONP")
return HttpResponse('func1("Steve")')
可以通过javascript动态地创建script标签,这样就可以灵活调用远程服务了。
<script>
function addScriptTag(src){
var script = document.createElement('script');
script.setAttribute("type", "text/javascript");
script.src = src;
document.body.appendChild(script);
}
function fun1(arg){
alert("Hello" + arg);
}
window.onload = function(){
addScriptTag("http://127.0.0.1:8002/get_byjsonp?callback=fetch");
}
</script>
17. jQuery对JSONP的实现
<script type="text/javascript">
$.getJSON("http://127.0.0.1:8001/get_byjsonp?callback=?", function(arg){
alert("hello" + arg);
});
</script>
注意:在url后面必须添加一个callback参数,这样getJSON方法才会知道是用JSONP方式去访问服务,callback后面的那个问号是内部自动生成的一个回调函数。
可以使用$.ajax方法来实现:
$.ajax({
url:"http://127.0.0.1:8001/get_byjsonp",
dataType:"jsonp",
jsonp:'callback',
success: function(data){
alert(data);
}
});
def get_byjsonp(req):
callback = req.GET.get("callback")
return HttpResponse("%s('yuan')" % callback)
18. Cookie
1)保存在用户浏览器端
2)可以主动清除
3)也可以被“伪造”
4)跨域名cookie不共享
5)浏览器可以设置禁用cookie
django案例:
from django.shortcuts import render,redirect
from app01 import models
# Create your views here.
def login(request):
models.Administrator.objects.create(
username = 'root',
password = 'root',
)
message = ""
if request.method == "POST":
user = request.POST.get('user')
pwd = request.POST.get('pwd')
c = models.Administrator.objects.filter(username=user, password=pwd).count()
if c:
# 在Cookie当中放置当前的用户名
rep = redirect('/index.html')
# 设置有效时间
rep.set_cookie('username', user, max_age=10)
rep.set_cookie('email', user+"@live.com")
return rep
else:
message = "用户名或密码错误"
return render(request, "login.html", {'msg': message})
def index(request):
# 如果用户已经登录,获取当前登录的用户名
# 否则返回登录页面
username = request.COOKIES.get('username')
email = request.COOKIES.get('email')
if username:
return render(request, "index.html", {'username': username, 'email':email})
else:
return redirect('/login.html')
7)path参数:“/”表示全局生效,“/xxxx”表示当前url生效
8)domain:顶层域名,例domain='alexander.com'
9)httponly:仅仅http网络传输使用
10)jquery操作cookie
html页面:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<script src="/static/jquery.cookie.js"></script>
<script src="/static/jquery-3.2.1.js"></script>
// $.cookie()
// 一个参数: $.cookie(k) 获取值
// 两个参数: $.cookie(k, v) 设置值
<script>
$.cookie('k','v', {"path": "/"})
</script>
</body>
</html>
11)Cookie的应用:
登录认证
- 敏感信息不宜放置在cookie中,敏感信息放在数据库,频繁操作数据库
加密Cookie,敏感信息(可能会解密)
rep.set_signed_cookie('email', user+"@live.com")
19. Session
session是服务器端的一个键值对
session内部机制依赖于cookie
# 获取session值
request.session['k']
request.session.get('k1', None)
# 设置session值
request.session['k1'] = v
request.session.setdefault('k1', 123) # 存在则不设置
# 删除session中的键值对
del request.session['k1']
request.session.clear()
# 所有键、值、键值对
request.session.keys()
request.session.values()
request.session.items()
request.session.iterkeys()
request.session.itervalues()
request.session.iteritems()
# 用户session的随机字符串
request.session.session_key
# 将所有session失效日期小于当前日期的数据删除
request.session.clear_expired()
# 检查用户session的随机字符串在数据可以总是否存在
request.session.exists("session_key")
# 删除当前用户的所有Session数据
request.session.delete("session_key")
20. Form类
1)创建Form类时,主要涉及“字段”和“插件”,字段用于对用户请求数据的验证,插件用于自动生成HTML
Field:
required=True, 是否允许为空
widget=None, HTML插件
label=None, 用于生成label标签或显示内容
initial=None, 初始值
help_text=' ', 帮助信息(在标签旁边显示)
error_message=None, 错误信息{'required': '不能为空', 'invalid': '格式错误'}
show_hidden_initial=False, 是否在当前插件后面再加一个隐藏的且具有默认值的插件(可用于检验两次输入输入是否一致)
validators=[], 自定义验证规则
localize=False, 是否支持本地化
disabled=False, 是否可以编辑
label_suffix=None label内容后缀
CharField(Field):
max_length=None, 最大长度
min_length=None, 最小长度
strip=True, 是否移除用户输入空白
IntegerField(Field):
max_value=None, 最大值
min_value=None, 最小值
FloatField(IntegerField)
DecimalField(IntegerField):
max_value=None, 最大值
min_value=None, 最小值
max_digits=None, 总长度
decimal_places=None, 小数位长度
BaseTemporalField(Field):
input_formats=None 时间格式化
DateField(BaseTemporalField) 格式:2015-09-01
TimeField(BaseTemporalField) 格式:11:22
DateTimeField(BaseTemporalField) 格式:2015-09-01 11:22
DurationField(Field) 时间间隔
RegexField(CharField):
regex, 自定制正则表达式
max_length=None, 最大长度
min_length=None, 最小长度
error_message=None, 忽略,错误信息使用error_message={'invalid':}
EmailField(CharField)
FileField(Field)
allow_empty_file=False 是否允许空文件
ImageField(FileField):
注:需要PIL模块,pip3 install Pillow
以上两个字典使用时,需要注意两点:
-form表单中 enctype="multipart/form-data"
-view函数中 obj = MyForm(request.POST, request.FILES)
URLField(Field)
BooleanField(Field)
NullBooleanField(BooleanField)
ChoiceField(Field):
choices=(), 选项,如:choices=((0, '上海'), (1, "北京"))
required=True, 是否必填
widget=None, 插件,默认select插件
label=None, Label内容
initial=None, 初始值
help_text, 帮助提示
ModelChoiceField(ChoiceField)
... django.forms.models.ModelChoiceField
queryset, # 查询数据库中的数据
empty_label='' # 默认空显示内容
to_field_name=None, # HTML中value的值对应的字段
limit_choices_to=None, # ModelForm中对queryset二次筛选
ModelMultipleChoiceField(ModelChoiceField)
TypedCHoiceField(ChoiceField)
coerce = lambda val: val 对选中的值进行一次转换
empty_value='' 空值的默认值
SplitDateTimeField(MultiValueField)
input_date_formats=None, 格式列表:['%Y--%m--%d', '%m%d/%Y', '%m/%d/%y'']
input_time_formats=None, 格式列表:['%H:%M:%S', '%H:%M:%S.%f', '%H:%M']
FilePathField(ChoiceField) 文件选项,目录下文件显示在页面中
path, 文件夹路径
match=None, 正则匹配
recursive=False, 递归下面的文件夹
allow_files=True, 允许文件
allow_folders=False, 允许文件夹
required=True,
widget=None,
label=None,
initial=None,
help_text=''
GenericIPAddressField
protocol='both' both,ipv4,ipv6支持的IP格式
unpack_ipv4=False 解析ipv4地址,如果是::ffff:192.0.2.1时,可解析为192.0.2.1,PS:protocol必须为both才能启用
SlugField(CharField) 数字,字母,下划线,减号(连字符)
UUIDField(CharField) uuid类型
2)Django内置插件, widget=
TextInput(Input)
NumberInput(TextInput)
EmailInput(TextInput)
URLInput(TextInput)
PasswordInput(TextInput)
HiddenInput(TextInput)
Textarea(Widget)
DateInput(DateTimeBaseInput)
DateTimeInput(DateTimeBaseInput)
TimeInput(DateTimeBaseInput)
CheckboxInput
Select
NullBooleanSelect
SelectMultiple
RadioSelect
CheckboxSelectMultiple
FileInput
ClearableFileInput
MultipleHiddenInput
SplitDateTimeWidget
SplitHiddenDateTimeWidget
SelectDateWidget
21. 请求头获取用户设备
request.environ.get('HTTP_USER_AGENT')
22. 循环实现评论数据结构
ret = []
comment_list_dict = {}
for row in comment_list:
row.update({'children': []})
comment_list_dict[row['id']] = row
for item in comment_list:
parent_row = comment_list_dict.get(item['parent_id'])
if not parent_row:
ret.append(item)
else:
parent_row['children'].append(item)
23. Model&Form&ModelForm:
Model:用于数据库操作
Form:用于用户请求的验证
ModelForm:用于数据库操作(部分),用于用户请求的验证(部分)
1)Model操作:
a. 数据表操作
Code First:创建类->自动生成表
DB First:创建表->自动生成类
字段:数字、字符串、时间、文件、关系
参数:用以指定生成数据库列信息;用于验证(admin、ModelForm);关系(一对一,一对多,多对多)
24. model数据库查询进阶操作
获取个数
models.tb.objects.filter(name='seven').count()
大于,小于
models.tb.objects.filter(id__gt=1) # 获取id大于1的值
models.tb.objects.filter(id__gte=1) # 获取id大于等于1的值
models.tb.objects.filter(id__lt=1) # 获取id小于10的值
models.tb.objects.filter(id__lte=1) # 获取id小于等于10的值
models.tb.objects.filter(id__lt=1, id__gt=1) # 获取id大于1且小于10的值
in
models.tb.objects.filter(id__in=[11,22,33]) # 获取id等于11,22,33的数据
models.tb.objects.exclude(id__in=[11,22,33])# not in
isnull
models.tb.objects.filter(pub_date__isnull=True)
contains
models.tb.objects.filter(name__contains="ven")
models.tb.objects.filter(name__icontains="ven") # icontains大小写不敏感
models.tb.objects.exclude(name__icontains="ven")
range
models.tb.objects.filter(id__range=[1,2]) # 范围between and
其他类似
startswith, istartswith, endswith, iendswith
order by
models.tb.objects.filter(name='seven').order_by('id') # asc
models.tb.objects.filter(name='seven').order_by('-id') # desc
group by
from django.db.models import Count, Min, Max, Sum
models.tb.objects.filter(c1=1).values('id').annotate(c=Count('num'))
select "app_tb"."id", count("app_tb", "num") as "c" from "app_tb" where "app_tb"."c1" = 1 group by "app_tb"."id"
limit, offset
models.tb.objects.all()[10:20]
regex正则匹配,iregex不区分大小写
Entry.objects.get(title__regex=r'^(An?|The)+')
Entry.objects.get(title__iregex=r'^(an?|the)+')
date
Entry.objects.filter(pub_date__date=datetime.date(2005,1,1))
Entry.objects.filter(pub_date__date__gt=datetime.date(2005,1,1))
year
Entry.objects.filter(pub_date__year=2005)
Entry.objects.filter(pub_date__year__gte=2005)
25.