注:适用于 2.x 版本
1.pip 命令安装方法
pip install Django #指定版本 Django==2.2.3
2.新建一个项目
django-admin startproject 项目名
3.新建项目下新建 app
django-admin startapp app名
4.启动
python manage.py runserver 0.0.0.0:8000 (IP:端口)
5.settings.py 文件配置
------------------
1.INSTALLED_APPS 添加创建app
INSTALLED_APPS = [
....xxx,
'app名1',
]
2.TEMPLATES 配置模板文件路径在 templates 文件下
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [os.path.join(BASE_DIR, 'templates')], #模板文件路径
'APP_DIRS': True,
...xxx
},
]
3.静态文件配置
STATIC_URL = '/static/' #静态指向别名 如:/static/index.css
STATICFILES_DIRS=(
os.path.join(BASE_DIR,'static'), #静态目录地址配置,一般放在static文件夹下
)
4.配置404
DEBUG = False
ALLOWED_HOSTS = ["*"]
6.urls.py 路由配置
from django.urls import include, path, re_path
from blog import views #自己创建app指向配置,一般指向views.py
urlpatterns = [
path('admin/', admin.site.urls),
path('', views.index),
path('cbv', views.CBV.as_view()), # class CBV形式
path('articles/<int:year>/<int:month>', views.year_archive),
path('blog/', include('blog.urls')), #分发url 在 blog/urls.py
re_path(r'page/(\d{1,4})',views.pageNum,name="page"), #正则用法
]
handler404=views.page404 #配置404
如:views.py
from django.shortcuts import render,HttpResponse,redirect
from django.views import View # class形式
from django.urls import reverse #获取别名 urls.py 的 name 指定值
class CBV(View):
def get(self,request):
return render(request,'index.html')
def post(self,request):
return render(request,'index.html')
def index(request):
return render(request,'index.html',{'title':'我是首页'})
def year_archive(request,year,month):
return render(request,'time.html',{'time':'%s - %s'%(year,month)})
def pageNum(request,num):
# reverse('page',args=(1,)) #获取urls.py 里别名 name="page" 的路径:page/1
return render(request,'page.html',{'num':num})
redirect('/show/111') #页面跳转
#配置404
def page404(request, exception):
return render(request,'404.html')
request 取值
-------
if request.method == 'GET':
request.GET.get('name')
elif request.method == 'POST':
request.POST.get('name')
request.path #获取路径 /home
request.get_full_path() #获取全路径 /home?age=11
7.templates模板用法:
变量语法:
{
obj:{
'name':66,
'list':[1,2]
}
}
{{obj.name}} 对象 , {{obj.list.0}} 列表
获取当前网址:{{ request.path }}
获取当前 GET 参数:{{ request.GET.urlencode }}
form 表单验证:{% csrf_token %} #不带回报403
settings.py 文件配置
MIDDLEWARE = [
# 'django.middleware.csrf.CsrfViewMiddleware', #取消csrf 验证
]
if 判断:
{% if age >= 90 %}
...
{% elif age >= 80 %}
...
{% else %}
...
{% endif %}
for 循环:
{% for athlete in athlete_list %}
<li>{{forloop.counter}}:{{ athlete.name }}</li>
{% empty %}
<li>抱歉,列表为空</li>
{% endfor %}
forloop.counter 索引从 1 开始算
forloop.counter0 索引从 0 开始算
forloop.revcounter 索引从最大长度到 1
forloop.revcounter0 索引从最大长度到 0
forloop.first 当遍历的元素为第一项时为真
forloop.last 当遍历的元素为最后一项时为真
forloop.parentloop 用在嵌套的 for 循环中,获取上一层 for 循环的 forloop
遍历字典
{% for key, value in info_dict.items %}
{{ key }}: {{ value }}
{% endfor %}
模块引入
{% include 'nav.html' %}
{% block content %}
<div>这里是默认内容,所有继承自这个模板的,如果不覆盖就显示这里的默认内容。</div>
{% endblock %}
模板继承
{% extends 'base.html' %}
数据库操作
-----------
#settings.py 文件配置
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': 'django', #数据库名称
'USER': 'root', #用户名
'PASSWORD': 'heng123456', #密码
'HOST': '', #地址 默认localhost
'PORI': '3306', #端口
}
}
#配置引擎
pip install PyMySQL #先安装PyMySQL
在当前项目__init__.py里配置
import pymysql
pymysql.install_as_MySQLdb()
创建表
python manage.py makemigrations #生成配置
python manage.py migrate #执行配置
报错:
# 找到base.py文件,注释掉 base.py 中如下部分(35/36行)
if version < (1, 3, 3):
raise ImproperlyConfigured("mysqlclient 1.3.3 or newer is required; you have %s" % Database.__version__)
此时仍会会报错,报错信息如下:
AttributeError: ‘str’ object has no attribute ‘decode’
#找到operations.py文件(146行),将decode改为encode
表记录操作
models.py里配置
from django.db import models
# 定义表
class Book(models.Model):
name=models.CharField(max_length=20)
price=models.IntegerField() #models.FloatField(3,1)
pub_data=models.DateField()
author=models.CharField(max_length=32,null=False)
#外键(默认关联主键),加参数 related_name="xxx" 设置反向查找名称, 默认是publish
publish=models.ForeignKey("Author",on_delete=models.CASCADE) # ForeignKey("self") 表示关联自己
#多对多(会新建个对应id表 info_id)
info=models.ManyToManyField("Info")
#取消 ForeignKey 外键约束,保留双下划线跨表查询功能:(外键约束会影响数据库性能推荐取消)
----
models.ForeignKey("Author",db_constraint=False) #取消外键约束
----
# ForeignKey 里的 on_delete 参数机制
-----------------------------------
参数说明:
on_delete有CASCADE、PROTECT、SET_NULL、SET_DEFAULT、SET()五个可选择的值
on_delete=None, # 删除关联表中的数据时,当前表与其关联的field的行为
on_delete=models.CASCADE, # 删除关联数据,与之关联也删除
on_delete=models.DO_NOTHING, # 删除关联数据,什么也不做
on_delete=models.PROTECT, # 删除关联数据,引发错误ProtectedError
# models.ForeignKey('关联表', on_delete=models.SET_NULL, blank=True, null=True)
on_delete=models.SET_NULL, # 删除关联数据,与之关联的值设置为null(前提FK字段需要设置为可空,一对一同理)
# models.ForeignKey('关联表', on_delete=models.SET_DEFAULT, default='默认值')
on_delete=models.SET_DEFAULT, # 删除关联数据,与之关联的值设置为默认值(前提FK字段需要设置默认值,一对一同理)
on_delete=models.SET(), # 删除关联数据,此值设置,会调用外面的值,可以是一个函数
a. 与之关联的值设置为指定值,设置:models.SET(值)
b. 与之关联的值设置为可执行对象的返回值,设置:models.SET(可执行对象)
-------------------------
# ManyToManyField 多对多
--------
参数说明:
symmetrical,只用在自己对自己进行关联的时候。比如说Friend,你的朋友是我,我的朋友是你。
through,如果不想要Django自动创建的多对多的关系表(默认建立就三列),可以通过指定through指定自己定义的中介表。
through_fields,在上面的基础上指定中间模型的**哪些字段**来建立是多对多关联。
db_table,设定多对多关系表的名称。
db_constraint,同上
#自定义第三张表如:
models.ManyToManyField(through='UserToTag') #加 through_fields=['u','t'] 相当于加 class Meta
class UserToTag(models.Model):
u=models.ForeignKey('User',db_constraint=False)
t=models.ForeignKey('Tag',db_constraint=False)
new_time=models.DateField()
class Meta:
#设置联合唯一,User和Tag不能再创建两个相同的否则报错
unique_together=[('u','t')]
db_table='UserToTag' #数据库表名
verbose_name_plural='用户表' # admin使用的名称
------------------------
表记录添加 ,一共有四种方法
例:
---
from blog.models import *
def addbook(request):
b=Book(name="python基础教程",price=67,author="小明",pub_data="2017-10-09")
b.save()
---
# 方法 1
Book.objects.create(name="python基础教程")
# 批量创建
objs = [
models.Book(name='r11'),
models.Book(name='r22')
]
models.Book.objects.bulk_create(objs, 10) # 10 是最多插入数
# 方法 2
b = Book(name="python基础教程",price=67)
b.save()
# 方法 3
b = Book()
b.name="python基础教程"
b.save()
# 方法 4,首先尝试获取,不存在就创建,可以防止重复
Book.objects.get_or_create(name="python基础教程",price=67)
# 返回值(object, True/False)
#表更新
------
批量更新 (filter是拿到的集合)
Book.objects.filter(name="python基础教程").update(name='xxx') # 名称中包含 "abc"的人 都改成 xxx
单个 object 更新
b = Book.objects.get(name="WeizhongTu")
b.name="WeizhongTu"
b.save() # 最后不要忘了保存!!!
如果存在,则更新,否则,创建, defaults 指定创建时或更新时的其他字段
obj, created = models.UserInfo.objects.update_or_create(username='root1', defaults={'email': '1111111','u_id': 2, 't_id': 1})
#表删除
------
Book.objects.filter(name="python基础教程").delete()
Book.objects.all().delete() # 删除所有 Person 记录
------
#表查询 注:filter和values通过 __下划线跨表查
b=Book.objects
b.filter(name="python基础教程") #条件查询返回集合
.values('name','age') #只显示两个值,vlaues 是返回字典形式 [{},{}]
.values('name','publish__author') # 跨表查publish表里的author字段 (publish 外键)
注:跨多表 publish__info__name # publish表里info外键表里的name字段
.values_list('name','age') #元组形式 [(),()]
b.exclude(id=3) #查询所有id不等于3的人
b.all() #查询所有 all()[:3] 支持支持切片
b.get(name="python基础教程") #取单个
b.filter(name="").first() #取第一个
b.all().last() #取最后一个
b.all().order_by('name') #查询结果排序
b.all().order_by('-name') # 在 column name 前加一个负号,可以实现倒序
b.all().order_by('name').reverse() #取反
b.all().values('name').distinct() #去重
.count() #计数
b.all().only('name','email') # only 是指只取当前这列的属性'name','email'
b.all().defer('name','email') # defer和only正好相反,除了括号内的属性其他都要取出来
------------
# 跨表查询优化(默认通过外键取值会触发一次查询,多次取多次触发)《优化重点 !!!》
# 跨表查询时用 select_related('a','b',..)
b.all().select_related('publish') #表优化减少sql请求(会一次拿到指定表的数据)
#select_related() 接受可变长参数,每个参数是需要获取的外键的字段名,以及外键的外键的字段名…。若要选择外键的外键需要使用两个下划线“__”来连接。
如:
obj = Person.objects.select_related('publish__info')
obj.publish.info
注:prefetch_related效果和select_related类似,不过使用的场景不同:
b.select_related 适用于外键和多对一的关系查询;
b.prefetch_related('外键字段') 适用于一对多或者多对多的查询
select_related() 也可以不加参数,这样表示要求Django尽可能深的select_related,但会浪费性能。
------------
# extra 用于额外的查询条件或者映射,如:子查询
Entry.objects.extra(select={'new_id': "select col from sometable where othercol > %s"}, select_params=(1,))
Entry.objects.extra(where=['headline=%s'], params=['Lennon'])
Entry.objects.extra(where=["foo='a' OR bar = 'a'", "baz = 'a'"])
Entry.objects.extra(select={'new_id': "select id from tb where id > %s"}, select_params=(1,), order_by=['-nid'])
取值例:
v = models.Uinfo.objects.all().extra(select={
'n':"select count(1) from app01_utype WHERE id=%s or id=%s",
'm':"select count(1) from app01_uinfo WHERE id=%s or id=%s",
},select_params=[1,2,3,4])
for i in v:
print(i.n,i.m,i.id)
------------
filter连接符
-----
filter(age__gt=10)
__exact 精确等于 like ‘aaa'
__iexact 精确等于 忽略大小写 ilike ‘aaa'
__contains 包含 like ‘%aaa%'
__icontains 包含 忽略大小写 ilike ‘%aaa%',但是对于sqlite来说,contains的作用效果等同于icontains。
__gt 大于
__gte 大于等于
__lt 小于
__lte 小于等于
__in=[1,3,5] 查询值为1,3,5的人
__startswith 以…开头
__istartswith 以…开头 忽略大小写
__endswith 以…结尾
__iendswith 以…结尾,忽略大小写
__range 在…范围内
__year 日期字段的年份
__month 日期字段的月份
__day 日期字段的日
__isnull=True/False
__overlap 集合至少有一个元素重合
__regex 匹配正则表达式
#多表操作
--------
添加记录 (publish 外键)
#publish_id=2
Book.objects.create(name="xx",publish_id=2)
#publish=object
publish_obj=Publish.objects.get(name="xx")
Book.objects.create(name="xx",publish=publish_obj.id)
#查询记录(通过对象)
#正向查询 (通过Book外键publish绑定的主键id 查publish里对应的数据)
book_obj=Book.objects.get(name="xx")
pub_obj=book_obj.publish
pub_obj.name
根据 publish 查 Book 的数据 (publish 外键名 下划线查询 __xx 对象名)
Book.objects.filter(publish__name="xx").values('name')
#反向查询 (通过publish反向查book里对应的数据)
pub_obj=Publish.objects.filter(name="xx")[0]
pub_obj.book_set.all().values('name')
通过Book绑定的外键 查Publish里对应的数据
Publish.objects.filter(book__name="xx").values('name')
注:OneToOneField 反向查询直接点名字就行,不用 _ 如:pub_obj.book
#多对多
正向
b=Book.objects.get(id=1) #Book的所有Info里的对应信息(底层通过外键来实现的)
b.info.all() #对应 info=models.ManyToManyField("Info")
反向
i=Info.objects.get(id=1)
i.book_set.all()
创建多对多关系
i=Info.objects.get(id=1)
b=Book.objects.get(id=5)
b.info.add(i) #添加
b.info.add([2,4]) #添加多个
b.info.remove(i) #删除 可以是id
b.info.remove([2,4]) #删除多个
b.info.clear() #删除所有绑定
b.info.set(1) #重置数据
b.info.set([1,2,3]) #重置多个
b.info.all() #查询所有关联
类似:left join 跨表查询 Book显示全部
Book.objects.filter(info__name="xx").values('name') #查看 book_info表里对应的book数据
聚合函数 aggregate
from django.db.models import Avg, Max, Min,Sum,Count #平均值:Avg() 求和:sum() 总数:Count()
b=Book.objects.all().aggregate(name=Avg("price")) #name 自己取的名字
b.name
分组 annotate
Book.objects.values('name').annotate(sum=Sum("price"))
查询 Q, F
from django.db.models import Q,F
Book.objects.all().update(price=F('price')+10) #相当于 update book set price=price+10;
Book.objects.filter(Q(price=10)|Q(name="小明"),age=10) # | 或操作 ~ 非操作 (Q 放前面)
# Q 添加多个用法
q = Q()
q.connector = 'OR' # 或操作
q.children.append((price,10))
q.children.append((name,"小明"))
Book.objects.filter(q)
# 迭代器取值 iterator (节约内存)
ret=Book.objects.all().iterator()
for i in ret:
print(i.name)
------------------
# 执行原始SQL查询
---------
1.导入django.db.connection对像,它代表当前数据库连接。
2.通过connection.cursor()得到一个游标对像。
3.使用cursor.execute(sql, [params])来执行SQL语句。
4.使用cursor.fetchone()或者cursor.fetchall()来返回记录集。
注:fetchall()返回的是元组的列表
例:
from django.db import connection, connections
cursor = connection.cursor()
#cursor = connections['default'].cursor() #指定sttings.py 里配置的数据库
cursor.execute("""
SELECT DISTINCT first_name
FROM people_person
WHERE last_name = %s""", ['Lennon'])
row = cursor.fetchone() #返回结果 ['John']
# models.Manager 整合 class
from django.db import connection, models
class PersonManager(models.Manager):
def first_names(self, last_name):
cursor = connection.cursor()
cursor.execute("""
SELECT DISTINCT first_name
FROM people_person
WHERE last_name = %s""", [last_name])
return [row[0] for row in cursor.fetchone()]
class Person(models.Model):
first_name = models.CharField(max_length=50)
last_name = models.CharField(max_length=50)
objects = PersonManager()
>>Person.objects.first_names('Lennon')
#返回结果 ['John', 'Cynthia']
---
#另一种原始SQL查询
Book.objects.raw("select id,name form book where id=%s",params=[12,]) #必须有id主键否则会报错
--------
#Django表model创建字段说明
-------------------------
一、字段
1、models.AutoField 自增列 = int(11)
如果没有的话,默认会生成一个名称为 id 的列,如果要显示的自定义一个自增列,必须将给列设置为主键 primary_key=True。
2、models.CharField 字符串字段
必须 max_length 参数
3、models.BooleanField 布尔类型=tinyint(1)
不能为空,Blank=True
4、models.ComaSeparatedIntegerField 用逗号分割的数字=varchar
继承CharField,所以必须 max_lenght 参数
5、models.DateField 日期类型 date
对于参数,auto_now = True 则每次更新都会更新这个时间;auto_now_add 则只是第一次创建添加,之后的更新不再改变。
6、models.DateTimeField 日期类型 datetime
同DateField的参数
7、models.Decimal 十进制小数类型 = decimal
必须指定整数位max_digits和小数位decimal_places
8、models.EmailField 字符串类型(正则表达式邮箱) =varchar
对字符串进行正则表达式
9、models.FloatField 浮点类型 = double (3,1) 第一个总数第二个小位数
10、models.IntegerField 整数
11、models.BigIntegerField 长整型
integer_field_ranges = {
'SmallIntegerField': (-32768, 32767),
'IntegerField': (-2147483648, 2147483647),
'BigIntegerField': (-9223372036854775808, 9223372036854775807),
'PositiveSmallIntegerField': (0, 32767),
'PositiveIntegerField': (0, 2147483647),
}
12、models.IPAddressField 字符串类型(ip4正则表达式)
13、models.GenericIPAddressField 字符串类型(ip4和ip6是可选的)
参数protocol可以是:both、ipv4、ipv6
验证时,会根据设置报错
14、models.NullBooleanField 允许为空的布尔类型
15、models.PositiveIntegerFiel 正Integer
16、models.PositiveSmallIntegerField 正smallInteger
17、models.SlugField 减号、下划线、字母、数字
18、models.SmallIntegerField 数字
数据库中的字段有:tinyint、smallint、int、bigint
19、models.TextField 字符串=longtext
20、models.TimeField 时间 HH:MM[:ss[.uuuuuu]]
21、models.URLField 字符串,地址正则表达式
22、models.BinaryField 二进制<br>23、models.ImageField 图片<br>24、models.FilePathField 文件
二、字段参数
1、null=True
数据库中字段是否可以为空
2、blank=True
django的 Admin 中添加数据时是否可允许空值
3、primary_key = False
主键,唯一不为空,对AutoField设置主键后,就会代替原来的自增 id 列
4、auto_now 和 auto_now_add
auto_now 自动创建---无论添加或修改,都是当前操作的时间
auto_now_add 自动创建---永远是创建时的时间
5、choices 获取对应值
set_value = (
(1, '确认'),
(2, '取消'),
)
class Back():
gender = models.CharField(max_length=2,choices = set_value)
Back.objects.filter(gender=1).first().get_gender_display() # gender 字段数据库值为 1 时得到值:确认
6、max_length 长度
7、default 默认值
8、verbose_name Admin中字段的显示名称
9、name|db_column 数据库中的字段名称
10、unique=True 不允许重复
11、db_index = True 数据库索引
12、editable=True 在Admin里是否可编辑
13、error_messages=None 错误提示
14、auto_created=False 自动创建
15、help_text 在Admin中提示帮助信息
16、validators=[]
17、upload-to
附录表之间的关系
1、一对多,models.ForeignKey(ColorDic) # 就是加一个外键
应用场景:在某表中创建一行数据时,有一个单选的下拉框(下拉框中的内容被用过一次就消失了)。
2、一对一,models.OneToOneField(OneModel) # 就是外键加唯一索引
应用场景:当一张表中创建一行数据时,有一个单选的下拉框(可以被重复选择)。
3、一对多,models.ManyToManyField(Author) # 建立第三张表,关联第三张表
应用场景:在某表中创建一行数据是,有一个可以多选的下拉框。
-------------------------
#序列化
------|
from django.core import serializers
obj = models.Student.objects.all().values()
#转成字典对象形式(推荐用法)
list(obj) #=> [{},{}]
#转成json格式但会有多层
#serializers.serialize('json',obj)
-------------------------
#分页设置
--------
from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger
arr=Book.objects.all()
#如 arr = ['john','paul','george','ringo','lucy','meiry','checy','wind','flow','rain']
p = Paginator(arr,3) # 3 一页显示3条,实例化分页对象
p.count # 10 对象总共10个元素
p.num_pages # 4 对象可分4页
p.page_range # xrange(1, 5) 对象页的可迭代范围
page1 = p.page(1) # 取对象的第一分页对象
page1.object_list # 第一分页对象的元素列表['john', 'paul', 'george']
page1.number # 第一分页对象的当前页值 1
page2 = p.page(2) # 取对象的第二分页对象
page2.object_list # 第二分页对象的元素列表 ['ringo', 'lucy', 'meiry']
page2.number # 第二分页对象的当前页码值 2
page1.has_previous() # 第一分页对象是否有前一页 False
page1.has_other_pages() # 第一分页对象是否有其它页 True
page2.has_previous() # 第二分页对象是否有前一页 True
page2.has_next() # 第二分页对象是否有下一页 True
page2.next_page_number() # 第二分页对象下一页码的值 3
page2.previous_page_number() # 第二分页对象的上一页码值 1
page2.start_index() # 第二分页对象的元素开始索引 4
page2.end_index() # 第2分页对象的元素结束索引 6
---------
#表单验证
------------------------
from django import forms
from django.forms import fields,widgets
from django.core.exceptions import ValidationError
from django.core.validators import RegexValidator
class ReForm(forms.Form):
name = fields.CharField(
min_length=2, #最小值
max_length=18, #最大值
required=True, #是否必填
error_messages={ #自定义错误信息
'required':'名称不能为空',
'min_length':'名字不能小于两位'
},
validators=[ # 自定制正则验证,可以定义多个
RegexValidator(r'^[0-9]\\d{5}$','邮政编码格式不正确'),
...
],
widget=widgets.Select() #定制html插件
)
author = fields.CharField(min_length=1,max_length=10,required=True,error_messages={
'required':'作者不能为空',
'max_length':'作者名字不能大于10位'
})
price = fields.IntegerField(
min_value=0, #最小值
max_value=50, #最大值
required=True,
error_messages={
'required':'价格不能为空',
'invalid':'必须为数字' #格式问题统一叫 invalid
})
#自定义单字段扩展 clean_*
def clean_name(self):
v = self.cleaned_data['name']
if Book.objects.filter(name=v).count():
raise ValidationError('名称已存在')
return v
#整体自定义扩展可以验证多字段
def clean(self):
obj = self.cleaned_data
name= obj.get('author')
age= obj.get('age')
if Book.objects.filter(name=name).count() and int(age)<12:
raise ValidationError('已存在作者年龄小于12不能再添加')
return self.cleaned_data
def addbook(request):
if request.method=="POST":
da=ReForm(request.POST)
obj={}
if da.is_valid():
obj=da.cleaned_data #成功数据,是字典格式
else:
return JsonResponse({'code':400,'message':da.errors))
Book.objects.create(**obj)
------------------
注:fields 字段说明
----------
Field
required=True#请求不能为空
widget=None#HTML插件
label=None#用于生成lable标签或显示内容
initial=None#初始值(第一次不验证)
help_text=''#帮助信息(在标签旁边显示)
error_messages=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:12
DateTimeField(BaseTemporalField)格式:2015-09-01 11:12
DurationField(Field) 时间间隔:%d %H:%M:%S.%f
...
RegexField(CharField)
regex="", 自定义判断的正则表达式
max_length=None, 最大长度
min_length=None, 最小长度
error_message=None, 忽略,错误信息使用 error_messages={'invalid': '...'}
EmailField(CharField)
...
FileField(Field)
allow_empty_file=False, 是否允许空文件
verbose_name_plural="admin里的名字",
upload_to="admin里上传的路径"
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)
... django.forms.models.ModelMultipleChoiceField
TypedChoiceField(ChoiceField)
coerce= lambda x:int(x) 对选中的值进行一次转换
empty_value= '' 空值的默认值
MultipleChoiceField(ChoiceField)
...
TypedMultipleChoiceField(MultipleChoiceField)
coerce = lambda val: val 对选中的每一个值进行一次转换
empty_value= '' 空值的默认值
ComboField(Field)
fields=() 使用多个验证,如下:即验证最大长度20,又验证邮箱格式
fields.ComboField(fields=[fields.CharField(max_length=20), fields.EmailField(),])
MultiValueField(Field)
PS: 抽象类,子类中可以实现聚合多个字典去匹配一个值,要配合MultiWidget使用
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类型
...
-----------------------
#文件上传
--------
前端
---
<div>
<input type="file" id="imgs"><button id="update">上传</button>
</div>
$('#update').click(function () {
var file = document.getElementById('imgs').files[0];
if (!file) {
return alert('请选择文件 !');
}
var obj = new FormData();
obj.append('imgs', file);
$.ajax({
type: "POST",
url: "/blog/update",
dataType: "json",
processData: false,
contentType: false,
data: obj,
success: function (msg) {
console.log(msg);
}
});
});
后端
---
import os,uuid
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
# BASE_DIR 路径是当前目录上两层
#form形式获取
#class ReForm(forms.Form):
# imgs=fields.FileField()
def index(request):
if request.method == 'POST':
#form形式获取
#obj=ReForm(request.POST,request.FILES)
#if obj.is_valid():
# img=obj.cleaned_data['imgs']
#正常获取
img=request.FILES.get('imgs')
#属性 img.name, img.size, img.content_type (image/png)
if img.content_type.find('image') == -1:
return HttpResponse("不是图片!")
name=str(uuid.uuid4().hex)
with open(os.path.join(BASE_DIR,'imgs',name+img.name),'wb') as f:
# img.chunks() 为可迭代对象
try:
for line in img.chunks():
f.write(line)
except:
HttpResponse("失败")
else:
HttpResponse("成功")
return HttpResponse("需要post请求")
-----------------
#cookies及session
--------
#cookies
def login(request):
request.COOKIES.get('name') #获取
ret=redirect('/index')
ret.set_cookie('name','yes',max_age=10) #设置 max_age=10 10秒失效
ret.delete_cookie('name') #删除
return ret
#session 默认保存15天
--------------------
def login(request):
# 获取、设置、删除Session中数据
request.session['k1']
request.session.get('k1',None)
request.session['k1'] = 123
request.session.setdefault('k1',123) # 存在则不设置
del request.session['k1']
# 所有 键、值、键值对
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")
request.session.clear() #只清空记录不删数据库数据
request.session.flush() #删除session数据库里的记录(优化内存)
request.session.set_expiry(value)
* 如果value是个整数,session会在些秒数后失效。
* 如果value是个datatime或timedelta,session就会在这个时间后失效。
* 如果value是0,用户关闭浏览器session就会失效。
* 如果value是None,session会依赖全局session失效策略。
Django默认支持Session,并且默认是将Session数据存储在数据库中,即:django_session 表中。
session 配置 settings.py
SESSION_ENGINE = 'django.contrib.sessions.backends.db' # 引擎(默认)
SESSION_COOKIE_NAME = "sessionid" # Session的cookie保存在浏览器上时的key,即:sessionid=随机字符串(默认)
SESSION_COOKIE_PATH = "/" # Session的cookie保存的路径(默认)
SESSION_COOKIE_DOMAIN = None # Session的cookie保存的域名(默认)
SESSION_COOKIE_SECURE = False # 是否Https传输cookie(默认)
SESSION_COOKIE_HTTPONLY = True # 是否Session的cookie只支持http传输(默认)
SESSION_COOKIE_AGE = 1209600 # Session的cookie失效日期(2周)(默认)
SESSION_EXPIRE_AT_BROWSER_CLOSE = False # 是否关闭浏览器使得Session过期(默认)
SESSION_SAVE_EVERY_REQUEST = False # 是否每次请求都保存Session,默认修改之后才保存(默认)
缓存Session
SESSION_ENGINE = 'django.contrib.sessions.backends.cache'# 引擎
SESSION_CACHE_ALIAS = 'default' # 使用的缓存别名(默认内存缓存,也可以是memcache),此处别名依赖缓存的设置
# 登录实例 Views.py
from django.shortcuts import render,redirect,HttpResponse
from django.http import JsonResponse
def login(request):
if request.method=='GET':
return render(request,'login.html')
elif request.method=="POST":
user=request.POST.get('username')
pwd=request.POST.get('password')
if user=="root" and pwd=="123":
if request.POST.get('box')=="1": #checkbox被按下
request.session.set_expiry(10) #session认证时间为10s,10s之后session认证失效
request.session['username']=user #user的值发送给session里的username
request.session['is_login']=True #认证为真
return redirect('/index')
else:
return redirect('/login')
return render(request,'login.html')
def index(request):
if request.session.get('is_login',None): #若session认证为真
return render(request,'index.html',{'username':request.session['username']})
else:
# 如果是列表需要加 JsonResponse([1,2,3],safe=False)
return JsonResponse({'code':400,'data':'非法登录 !'})
def logout(request): #撤销
request.session.flush() #删除session数据库里的记录(优化内存)
return redirect('/login')
------
#django内置登录
--
from django.contrib.auth import authenticate,login,logout
#验证登录
def islogin(request):
error_msg=""
if request.method=="POST":
username=request.POST.get("username")
password=request.POST.get("password")
#查询django生成的auth_user表里有没有数据,没有返回None
user=authenticate(username=username,password=password)
if user:
login(request,user)
return redirect(request.GET.get('next',"/"))
else:
error_msg='用户名密码错误 !'
print(username,password,sep=": ")
return render(request, 'login.html',{'error_msg':error_msg})
#退出登录
def acc_logout(request):
logout(request)
return render(request, 'login.html')
#验证是否登录
from django.contrib.auth.decorators import login_required
#装饰器过滤是否登录 没登录就会跳到登录页 seitings.py 里配置 LOGIN_URL="/login"
@login_required
def home(request):
pass
-------------
# admin使用
-------
1.admin.py配置
from django.contrib import admin
from blog import models
class BookAdmin(admin.ModelAdmin):
'''以下都是可选''
list_display=('id','name','author','price','pub_data') #显示字段
list_editable=('name','author','price') #可编辑字段
list_per_page=2 #分页
search_fields=('id','name') #加搜索 id,name
list_filter=('author','price') #加过滤器
ordering=('price') #排序 ('-price')降序
admin.site.register(models.Book,BookAdmin) # BookAdmin 配置显示字段
admin.site.register(models.Author) # 注册models里的表 Book,Author
2.创建用户名密码
python manage.py createsuperuser
设置中文 settings.py
LANGUAGE_CODE = 'zh-Hans'
-------------------------