文章目录
使用Django创建一个项目
python3.6 + Django1.11
创建一个项目
django-admin startproject [mysite]此处自定义项目名字,不可是中文
生成文件目录
py@py-PC:~/text/mysite$ tree
.
├── db.sqlite3
├── manage.py
├── mysite
│ ├── __init__.py
│ ├── __pycache__
│ │ ├── __init__.cpython-36.pyc
│ │ ├── settings.cpython-36.pyc
│ │ ├── urls.cpython-36.pyc
│ │ └── wsgi.cpython-36.pyc
│ ├── settings.py
│ ├── urls.py
│ └── wsgi.py
在项目中创建一个app
在manage.py 的同级目录中执行:
python3 manage.py startapp [myweb]自定义app名字,不可以是中文
生成文件目录
py@py-PC:~/text$ tree
.
└── mysite
├── db.sqlite3
├── manage.py 【启动文件】
├── mysite
│ ├── __init__.py
│ ├── settings.py 【配置文件】
│ ├── urls.py 【主路由】
│ └── wsgi.py
├── myweb 【创建app应用的时候生成的】
│ ├── admin.py
│ ├── apps.py
│ ├── __init__.py
│ ├── migrations
│ │ └── __init__.py
│ ├── models.py 【创建库->表】
│ ├── tests.py
│ ├── urls.py 【子路由】
│ └── views.py 【视图】
└── templates 【网页文件夹,MVT模型】
└── xx.html
创建应用的步骤
-
执行创建app命令【创建myweb】
-
在myweb/views.py中写入
-
# render是用来返回页面的 from django.shortcuts import render # HttpResponse是用来返回数据或者html标签内容的 from django.http import HttpResponse def index(request,[k]): return HttpResponse('')返回字符串 return HttpResponse('<><>')返回标签 def xxx(request,[k]) return render(request,'xxx.html'k)====返回的是====/templaters/目录下面的html文件
-
-
修改主路由/mysite/urls.py
-
from django.conf import url,include from django.contrip import admin urlpatterns = [ # 这个url路由是主路由的admin管理员账户 url(r'^admin/',admin.site.urls), # 这个主路由的正则是^什么都不限制,他包括myweb下的urls.py这个子路由,交给子路由去处理 url(r'^',include('myweb.urls')), ]
-
-
在/myweb/目录下创建子路由urls.py
-
# 子路由的url是引用的django.conf.url from django.conf.urls import url # 子路由处理后需要执行视图中的方法,所以要引用当前目录想的view.py这个视图 from . import views urlpatterns = [ # 匹配正字hello开头/结尾 执行views下的index方法 url(r'^hello$/',views.index), # 匹配正则[0-9]数字开头匹配任意四位数子,执行views下的xxx方法 url(r'([0-9]{4})$/',views.xxx), ]
-
-
编辑配置文件/mysite/setting.py
-
# 编辑监听端口号为任意端口号 ALLOWD_HOSTS = ['*'] # 编辑templates文件路径,为根目录下的templates文件夹 TEMPLATES = [ ,'DIR':[os.path.join(BAST_DIR,"templates")], ]
-
-
服务请求的执行过程
用户在浏览器访问url地址的时候,django服务器接受请求----->url地址交给主路由的正则进行匹配—>交给子路由的正则匹配---->交个视图函数处理----->视图函数执行操作,返回HttpResponse或者render---->render的时候会从配置文件中查找template目录的路径
使用模板
-
配置模板的引擎
-
#配置项目的配置文件/mysite/setting.py TEMPLATES = [ { 'BACKEND':'django.template.backends.django.DjangoTemplates', 'DIRS':[os.path.join(BASE_DIR,'templates')], 'APP_DIRS':True, 'OPTIONS':{ 'context_processors':[ 'django.template.context_processors.debug', 'django.template.contex_processors.request', 'django.contrib.auth.context_processors.auth', 'django.contrib.messages.context_processors.messages', ], } } ]
-
-
模板都放在manage.py同级目录下的templates文件夹下面
- 模板文件夹用来存放html页面,当render返回html页面的时候,会来这里匹配
-
变更访问地址的端口号
- 默认端口号8000 在配置文件中ALLOWED_HOSTS = [’*’]
- 设置监听的端口号是任意端口号
- 使用自定义端口号启动服务python3 manage.py runserver 0:9000
路由的匹配规则
-
路由安装顺序执行
-
路由可以使用()来捕获url请求中的一部分参数来使用
-
例如:
-
请求url路径为 http://127.0.0.1:9000/articles/2014/ 路由的规则 url(r'articles/([0-9]{4})/$',view.year_archeive), 视图中的视图函数 def year_archive(request,y): print(y) return HttpResponse('year_archive') # 注意:在有()的路由规则,那么对应的视图函数中必须给定形参,有几个()给几个形参 # 路由参数 正则表达式命名组 在视图函数中叫关键字参数,变量名要和路由规则中定义的一致 # 命名组的关键字是 (?P<name>正则) 其中<name>就是命名组的命名,相对应的视图函数就要使用关键字参数 url(r'abc/(?P<year>[0-9]Z{4})/$',views.abc_2003), # 视图函数 def abc_2003(request,year): print(year) return HttpResponse('abc_2003')
-
参数的默认值 两个路由规则指向同一个视图函数
-
# 参数默认值 url(r'^user/list/$',views.userlist), url(r'^user/list/(?P<page>[0-9]+)',views.userlist), # 视图函数 def userlist(request,page=1): print(page) return HttpResponse('userlist')
-
URL的反向解析
-
通过对定义的路由添加名字,动态解析路由的地址
-
如果在视图、模板中使用硬编码的链接,那么在urlconf发生改变时,维护特别麻烦
-
# 动态解析url的规则,可以在定义路由规则时候,给路由起个名字 url(r'^goods/list/$',views.goodslist,name='glist'), # 在模板中直接是用url标签来通过路由的名字,解析路由的地址 <a href='{% url "glist" %}'>商品列表:反向解析格式</a>
-
# 注意,路由规则中如果有参数要求,那么在使用url进行反向解析的时候,必须给定参数 url(r'^order/list/([0-9]+)/$',views.orderlist,name='olist'), <a href="{% url 'olist' 100 %}" >订单列表:反向解析格式</a> # 在模板中反向解析{% url 'glist' %} # 在视图函数中使用反向解析 reverse('glist')
模型
-
django中通过模型来控制数据库
模型是定义好的Model类,自定义的模型继承这个基础类,自定义类中定义的属性便成为了数据库表格中的字段,类名成为了表格的名字
Model提供了一套操作数据的APT,不用直接操作数据库,解耦,减少工作量,不会因更换数据库产生无效劳动
例如:
class Users(Model):
username = models.CharField(max_length=100)
# 结果是在数据库中生成了一个名字为myweb_Users的表格
# 这个表格中会自动生成id字段【自增】以及生成username字段,类型char最大长度100
模型和数据库的关系
ORM 对象 关系 映射
任务是:
- 根据类,生成表结构
- 将对象,列表的操作,转换成为sql语句
- 将sql查询的结果转换为对象、列表
例如:
我们有个表Users
id username
1 张三
我们想获取张三
# select * from Users where id = 1;
ob = Users.objects.get(id = 1)
# ob 是一个对象 objects
name = ob.username
如果我们想获取所有数据
# select * from Users;
obs = Users.objects.all()
# obs的结果是一个列表[objects,objects....]
为什么要用模型?
MVC 解耦 处理数据 轻松控制
模型的使用
-
安装数据库 和 pymysql
-
在数据库中建立一个库 字符集 utf-8
-
-
DATABASES = { 'default': { 'ENGINE': 'django.db.backends.mysql', 'NAME': 'mydb',#选择数据库的名,请确认你的mysql中有这个库 'USER': 'root', 'PASSWORD': '123456', 'HOST': 'localhost', 'PORT': '3306', } }
-
-
mysite/init.py
-
import pymysql pymysql.install_as_MySQLdb()
-
-
模型的定义 在myweb/models.py
-
确定当前应用myweb是否在settings.py文件中配置
-
INSTALLED_APPS = [ 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', 'myweb', # 这里是我们的app ]
定义模型
from django.db import models class Users(models.Model): username = models.CharField(max_length=32) password = models.CharField(max_length=32) email = models.CharField(max_lenght=100) age = models.IntegerField() def __str__(self): return self,username class Stu(models.Model): sname = models.CharField(max_length=50) age = models.IntegerField() # 通过定义元选项,可以自定义表名 class Meta(): db_table = 'Stus' # 那么表名接受自定义 # 添加字段的后两个选择 sex = models.CharField(max_length=50,[default='',null=]) # 默认自动添加自增主键id,而且默认每个字段不能为空,所以在新加入字段的时候,会出现两个选择 # 1 给现有的数据添加同统一默认值 # 2 退出添加字段,修改字段属性,给定默认值,或者允许为空 # 可以更改字段的名字,但是更改数据类型,很容易出现错误
-
-
生成迁移文件
- python3 manage.py makemigrations
-
执行迁移动作
- python3 manage.py migrate
-
生成很多表 但是只有myweb_users是我们主动创建的
注意:如果没有指定表名,那么默认是应用名_类名的全小写
操作模型
所有的操作都是视图函数去执行,所以,我们需要将models.py文件导入到views.py文件之中
在views.py中加入 from . import Users,Stu
views.py中的查询操作
def mod_test(request):
obs = Users.abjects.all()
print(obs)
# 结果是个查询集 可以说一个列表
# <Queryset [<Users: Users object>,<Users: Users object>]>
# 如果在模型中定义 __str__()魔术方法,返回self.username 那么print,或者str转换会显示详细的信息
views.py中的添加操作
def addtest(request):
# 实例化Users对象,这个对象对应着表中的一条记录
ob = Users()
ob.username = '李四'
ob.email = 'ls@qq.com'
ob.age = 28
ob.save()
# 或者
data = {'username':'王五','email':'ww@qq.com','age':26}
ob = Users.objects.create(**data)
属性命名规则
- 不可以使用保留关键字
- 不可以使用双下划线
属性定义
- 模型的属性就是字段,而且需定义字段类型
- 导入from django.db import models
- 通过models.xxxField关键字创建属性
- 数据删除只做逻辑删除,不做物理删除,通过isDelete属性结合布尔值,标记为逻辑删除(这个标记在python中是True和False在数据库中是1和0)
增删改查
model配置
class Vipuser(models.Model):
username = models.CharField(max_length=50)
email = models.CharField(max_length = 100)
phone = models.CharField(max_length = 11)
age = models.IntegerField()
sex = models.CharField(max_length=1)
# 添加时间
addtime = models.DateTimeField(auto_now_add=True)
路由设置:
# 会员管理
<路由>
# 显示添加操作的表单
url(r'^user/add/$',views.user_add,name='useradd'),
# 执行添加的操作并且跳转
url(r'^user/insert/$',views.user_insert,name='userinsert'),
# 执行显示列表操作
url(r'^user/list/$',views.user_list,name='userlist'),
# 执行删除操作
url(r'^user/del/(?P<uid>[0-9]+)/$',views.user_del,name='userdel'),
# 执行修改前form表单展示操作
url(r'^user/edit/$',views.user_edit,name='useredit'),
# 执行点击修改后修改数据操作
url(r'^user/update/$',views.user_update,name='userupdate'),
views视图函数
<views函数>
# 返回表单页面
def user_add(request):
return render(request,'add.html')
# 执行添加操作
def user_insert(requers):
# 获取数据
data = request.POST.dict()
# 删除csrf验证码
data.pop('csrfmiddlewaretoken')
# 创建数据
try:
# 注意:先将Vipuser这个model导入到views.py这个脚本,使用reverse做动态反向解析要导入包
# from django.core.urlresolvers import reverse
ob = Vipuser.objects.create(**data)
return HttpResponse('<script>alert("success");location.href="'+reverse('userlist')+'"</script>')
except:
return HttpResponse('<script>alert("fail");location.href="'+reverse('useradd')+'"</script>')
# 执行列表上显示数据
def user_list(request):
# 获取数据
data = Vipuser.objects.all()
# 分配数据 为什么要设置一个字典? 因为render的第三个参数要求传入一个字典
context = {'ulist':data}
# 解析模板
return render(request,'user/list.html',context)
# 执行删除操作
def user_del(request,uid):
try:
# 获取要删除的用户对象
ob = Vipuser.objects.get(id=uid)
# 将获取的数据删除
ob.delete()
# 提示,并跳转到列表页
return HttpResponse('<script>alert("删除成功");location.href="'+reverse('userlist')+'"</script>')
except:
# 失败跳转到添加页面
return HttpResponse('<script>alert("删除失败");location.href="'+reverse('useradd')+'"</script>')
# 执行修改前form表单展示操作
def user_edit(request):
# 从a标签的?uid={}拼接部分获取uid
uid = request.GET.get('uid')
# 获取单条数据
ob = Vipuser.object.get(id=uid)
# 分配数据
context = {'uinfo':ob}
# 解析模板
return render(request,'user/edit.html',context)
#执行修改操作
def user_update(request):
try:
# 获取数据
uid = request.POST['uid']
ob = Vipuser.objects.get(id=uid)
# 依次修改
ob.username = request.POST['username']
ob.email = request.POST['email']
ob.sex = request.POST['sex']
ob.age = request.POST['age']
ob.phone = request.POST['phone']
# 保存
ob.save()
# 提示并且返回list页面
return HttpResponse('<script>alert("修改成功");location.href="'+reverse('userlist')+'"</script>')
except:
return HttpResponse('<script>alert("修改失败");location.href="'+reverse('useradd')+'"</script>')
html页面
首页
<ul>
<li><a href="{% url 'useradd' %}">会员添加</a></li>
<li><a href="{% url 'userlist' %}">会员列表</a></li>
</ul>
表单页面
<form action='{% url "userinsert" %}' method='POST'>
<!-- csrf_token 验证加强post传输的安全 -->
{% csrf_token %}
用户名:<input type="text" name="username"><br>
邮箱:<input type="text" name="email"><br>
手机号:<input type="text" name="phone"><br>
年龄:<input type="text" name="age"><br>
性别:
<input type="radio" name="sex" value="0">女
<input type="radio" name="sex" value="1">男
<br>
<button>添加</button>
</form>
表格页面
<center>
<table border="1px" cellspacing="0" width="800px">
<tr>
<th>ID号</th>
<th>姓名</th>
<th>邮箱</th>
<th>手机号</th>
<th>年龄</th>
<th>性别</th>
<th>创建时间</th>
<th>操作</th>
</tr>
{% for i in ulist %}
<tr>
<td>{{ i.id }}</td>
<td>{{ i.username }}</td>
<td>{{ i.email }}</td>
<td>{{ i.phone }}</td>
<td>{{ i.age }}</td>
<td>{% if i.sex == '0' %}女{% else %}男{% endif %}</td>
<!-- |date:这里用到了django的时间过滤器,将时间格式化输出 -->
<td>{{ i.addtime|date:'Y-m-d H:i:s' }}</td>
<td><a href="{% url 'userdel' i.id %}">删除</a> |
<a href="{% url 'useredit' %}?uid={{ i.id }}">修改</a>
</td>
</tr>
{% endfor %}
</table>
</center>
edit页面
<center>
<form action="{% url 'userupdate' %}" method="post">
<!-- csrf_token 验证加强post传输的安全 -->
{% csrf_token %}
<input type="hidden" name="uid" value="{{ uinfo.id }}">
用户名:<input type="text" name="username" value="{{ uinfo.username }}"><br>
邮箱:<input type="text" name="email" value="{{ uinfo.email }}"><br>
手机号:<input type="text" name="phone" value="{{ uinfo.phone }}"><br>
年龄:<input type="text" name="age" value="{{ uinfo.age }}"><br>
性别:
{% if uinfo.sex == '0' %}
<input type="radio" name="sex" value="0" checked>女
<input type="radio" name="sex" value="1">男
{% else %}
<input type="radio" name="sex" value="0">女
<input type="radio" name="sex" value="1" checked>男
{% endif %}
<br>
<button>修改</button>
</form>
</center>
配置文件时区修改
LANGUAGE_CODE = 'en-us'
# TIME_ZONE = 'UTC'
TIME_ZONE = 'Asia/Shanghai' # 亚洲/上海
USE_I18N = True
USE_L10N = True
USE_TZ = False # 原来为True 改为 False
模型关系
一对一
模型之间的一一对应关系
外键有物理外键和逻辑外键,物理外键是单独设立的外键字段,可以在两个表的任意一个表中,逻辑外键一般是使用id号的一一对应关系
屋里外键的优点和缺点都是解耦,缺点在于,删除某个数据的时候如果这个数据是被依赖的外键,那么将无法删除,所以要先删除关系,再删除数据
例如:
model模型
# 现在有两张表,第一张是用户的主要信息,第二张是详细信息,两张表的数据是一一对应的关系
class Vipuser(models.Model):
username = models.CharField(max_length=50)
email = models.CharField(max_length=100)
phone = models.CharField(max_length=11)
age = models.IntegerField()
sex = models.CharField(max_length=1)
addtime = models.DateTimeField(auto_now_add=True)
# 模型关系,建立一个UserInfo表来记录详细信息
# 在副表userinfo中添加一对一关系,关联vipuser主表
class UserInfo(models.Model):
# 一对一关系第一个参数是 所关联的模型名称,第二个是是否关联删除
uid = models.OneToOneField(Vipuser, on_delete=models.CASCADE)
xueli = models.CharField(max_length=10)
yuanxiao = models.CharField(max_length=20)
jiguan = models.CharField(max_length=20)
路由
# 模型关系1对1
url(r'model/one/$', views.one, name='one'),
url(r'model/two/$', views.two, name='two'),
url(r'model/three/$', views.three, name='three'),
views视图函数
# 模型关系1对1
def one(request):
# 添加
# 创建用户
data = {
'username': '李四',
'age': 18,
'email': 'lis@qq.com',
'phone': '11111',
'sex': 1,
}
u = Vipuser.objects.create(**data)
# 创建详情 在django中外键是能给实例化的对象,不能直接给id数字
uidata = {
'uid': u,
'xueli': '本科',
'yuanxiao': '山东大学',
'jiguan': '山东',
}
ui = UserInfo.objects.create(**uidata)
return HttpResponse("模型关系一对一")
def two(request):
# 删除用户 删除用户的时候也将关联删除用户的详情,但是如果删除副表数据,却不会删除主表数据,删除主表数据,会删除附表数据
u = Vipuser.objects.first()
u.delete()
return HttpResponse('执行了删除的操作')
def three(request):
# 查询可以根据主表查附表,也可以根据副表查主表
# 根据用户查详情
u = Vipuser.objects.first()
# 获取用户的Username
print(u.username)
# 获取用户的详情的yuanxiao,主表获取副表的时候直接对象后面跟表名然后跟字段就行
print(u.userinfo.yuanxiao)
u2 = UserInfo.objects.first()
# 根据副表查询主表就需要在附表对象的后面跟外键字段,再跟要查询的主表字段
print(u2.uid.sex)
print(u2.xueli)
return HttpResponse('执行了查询的操作')
一对多
一个a表数据对应多个b表数据,多个b表数据对应一个a表数据
例如:
一个班级有多个学员,多个学员都在一个班级
一个新闻分类有多个新闻,多个新闻是一个类新闻
一个商品分类下有多个商品
例如:
model模型 类别 和 商品的一对多关系
# 模型的一对多关系
# 类别
class Types(models.Model):
name = models.CharField(max_length=10)
# 商品
class Goods(models.Model):
# 第一个参数to指向的是Types这个主表,to_field参数指向的主表中的对应的字段
tid = models.ForeignKey(to='Types', to_field='id')
title = models.CharField(max_length=255)
price = models.IntegerField()
def __str__(self):
return self.title
url路由
url(r'model/duoone/$', views.duo_one, name='duoone'),
url(r'model/duotwo/$', views.duo_two, name='duotwo'),
url(r'model/duothree/$', views.duo_three, name='duothree'),
url(r'model/duothree2/$', views.duo_three2, name='duothree2'),
views视图函数
# 一对多的关系
# 添加
def duo_one(request):
t = Types.objects.create(**{'id': 3, 'name': '电视'})
g1 = Goods.objects.create(**{'title': '小米电视', 'price': 3999, 'tid': t})
g1 = Goods.objects.create(**{'title': 'TCL电视', 'price': 1999, 'tid': t})
return HttpResponse('添加数据成功')
# 删除
def duo_two(request):
# 删除分类之后,相对应的商品也会被删除,但是删除商品后不会影响分类
t = Types.objects.first()
t.delete()
return HttpResponse('删除了一个分类')
# 查询
def duo_three(request):
# 根据分类获取分类下的商品
t = Types.objects.first()
print(t.name)
print(t.goods_set.all())
print(t.goods_set.count())
return HttpResponse("执行了一次查询")
def duo_three2(request):
# 根据商品查询商品的分类
g = Goods.objects.last()
print(g.title)
print(g.tid.name)
return HttpResponse('执行了一次查询操作')
多对多
一个班级有多个老师,一个老师带多个班级
一本书有多个标签,一个标签有多本书
books 【book表】
id title author
tags 【tag表】
id name
books_tags 【所依赖的第三张表】
bookid tagid
多对多的关系,将关系连接字段放在两个模型的任意一个表中都可以,没有主附表之分
例如:
model模型
# 模型多对多关系
# book表
class Books(models.Model):
title = models.CharField(max_length=100)
def __str__(self):
return self.title
# tag表
class Tags(models.Model):
name = models.CharField(max_length=100)
# 多对多关系连接字段 ,参数to指向关联的表
bid = models.ManyToManyField(to='Books')
def __str__(self):
return self.name
路由
url(r'model/bookone/$', views.book_one, name='bookone'),
url(r'model/booktwo/$', views.book_two, name='booktwo'),
url(r'model/bookthree/$', views.book_three, name='bookthree'),
views视图函数
# 多对多模型的添加
def book_one(request):
# 创建三本书,和 三个标签
b1 = Books.objects.create(**{'title': '《python从零开始》'})
b2 = Books.objects.create(**{'title': '《php兄弟连》'})
t1 = Tags.objects.create(**{'name': 'IT编程'})
t2 = Tags.objects.create(**{'name': 'python'})
t3 = Tags.objects.create(**{'name': 'php'})
# 给标签添加书的对应关系add和set两个方法效果一样
t1.bid.set([b1, b2])
t2.bid.add(b1)
t3.bid.add(b2)
'''
或者给书添加标签的对应关系,这两种方式都可以
b1.tags_set.set([t1,t2])
b2.tags_set.set([t1,t3])
清空某个对象的所有关系
b = Books.objects.first()
将b这本书的对应关系清空
b.tags_set.clear()
'''
return HttpResponse("执行了多对多的添加操作")
# 多对多的删除操作,删除任意一方对另外一方不影响,只会将关系表中的关系连带的删除
# 查询 获取某本书的所有的标签
def book_two(request):
# 获取书对象
b = Books.objects.last()
print(b.title)
print(b.tags_set.all())
return HttpResponse('执行了一次根据书查询标签的操作')
# 获取一个标签下面的所有书
def book_three(request):
# 获取书对象
t = Tags.objects.first()
print(t.name)
print(t.bid.all())
return HttpResponse('执行了一次根据标签查询书的操作')
views视图
简单的返回信息或者html标签
from django.http import HttpResponse
import datetime
def current_datetime(request)
now = datetime.datetime.now()
html = '<html><body>It is now %s.</body></html>'%now
return HttpResponse(html)
返回常见的错误
from django.http import HttpResponseNotFound,HttpResponse,Http404
# 直接返回404,不加载404模板页面
return HttpResponseNotFound('<h1>访问的页面不见了</h1>')
# 直接返回一个status状态码
return HttpResponse(status=403)404 500
# 返回一个自定义在templates下的404页面
raise Http404("Poll doex not exist")
重定向
重定向就是通过各种方式将网络请求转向其他位置
from django.shortcuts import redirect
from django.core.urlresolvers import reverse
# redirect的重定向需要一个url地址
return redirect(reverse('urlname'))
# 通过JavaScript重定向
return HttpResponse('<script>alert("xxx");location.href="+reverse('urlname')+"</script>')
# 加载一个提醒信息的跳转页面~~还有多久将执行跳转,计时器
context = {'info':'数据添加成功','u':'/userindex'}
return render(request,'info.html',context)
request对象的几个属性
request.path # 获取请求路径str
request.method # 获取请求方法str
request.encoding # 获取提交数据的编码格式str
request.GET # 获取GET方式提交数据的类字典对象
request.POST # 获取POST方式体检数据的类字典对象
request.FILES # 获取文件上传提交的类字典对象
request.COOKIS # 一个标准的python字典,包含所有cookie 键值对
request.session # 获取可读写的session类字典对象
cookie
储存在浏览器中的状态信息,是一个类字典
用法:
设置cookie
# 获取HttpResponse对象
res = HttpResponse()
# 为对象设置cookie 不可使用中文
res.set_cookie('name','zhangsan')
# 返回相应对象
return res
获取cookie
# 读取
a = request.COOKIES.get('name',None)
if a:
return HttpResponse('cookie的读取:'+a)
else:
return HttpResponse('cookie不存在')
session
session是储存在服务器数据库中的一个类字典的状态信息
方法:
# 设置session
request.session.['Vipuser'] = {'name':'张三','age':18,'sex':0}
# session获取
request.session.get('Vipuser',None)
# 在不中断会话的前提下可以继续添加session,就是一个字典套字典
# 删除session三个方式
# 只删除一个键值对
del request.session['Vipuser']
# 删除会话,不删除记录
request.session.clear()
# 删除会话也删除记录
request.session.flush()
验证码-是块砖
# 验证码
def verifycode(request):
#引入绘图模块
from PIL import Image, ImageDraw, ImageFont
#引入随机函数模块
import random
#定义变量,用于画面的背景色、宽、高
bgcolor = (random.randrange(20, 100), random.randrange(
20, 100), 255)
width = 100
height = 25
#创建画面对象
im = Image.new('RGB', (width, height), bgcolor)
#创建画笔对象
draw = ImageDraw.Draw(im)
#调用画笔的point()函数绘制噪点
for i in range(0, 100):
xy = (random.randrange(0, width), random.randrange(0, height))
fill = (random.randrange(0, 255), 255, random.randrange(0, 255))
draw.point(xy, fill=fill)
#定义验证码的备选值
# str1 = 'ABCD123EFGHIJK456LMNOPQRS789TUVWXYZ0'
str1 = '123456789'
#随机选取4个值作为验证码
rand_str = ''
for i in range(0, 4):
rand_str += str1[random.randrange(0, len(str1))]
#构造字体对象
font = ImageFont.truetype('FreeMono.ttf', 23)
#构造字体颜色
fontcolor = (255, random.randrange(0, 255), random.randrange(0, 255))
#绘制4个字
draw.text((5, 2), rand_str[0], font=font, fill=fontcolor)
draw.text((25, 2), rand_str[1], font=font, fill=fontcolor)
draw.text((50, 2), rand_str[2], font=font, fill=fontcolor)
draw.text((75, 2), rand_str[3], font=font, fill=fontcolor)
#释放画笔
del draw
#存入session,用于做进一步验证
request.session['verifycode'] = rand_str
#内存文件操作
import io
buf = io.BytesIO()
#将图片保存在内存中,文件类型为png
im.save(buf, 'png')
#将内存中的图片数据返回给客户端,MIME类型为图片png
return HttpResponse(buf.getvalue(), 'image/png')
四级联动
models模型
class City(models.Model):
name = models.CharField(max_length=255)
level = models.IntegerField()
upid = models.IntegerField()
class Meta:
db_table = 'citys'
# 路由
url(r'^showcity/$',views.showcity,name='showcity'),
url(r'^getcity/$',views.getcity,name='getcity'),
# views视图函数
def showcity(request):
# 查询一级城市
data = City.objects.filter(level=1)
context = {'data':data}
return render(request,'city.html',context)
def getcity(request):
# 根据请求发送过来的id做uid查询
uid = request.GET.get('id')
# 根据id获取数据
data = City.objects.filter(upid=uid).values()
# 返回json数据
return JsonResponse(list(data),safe=False)
<select>
<option>--请选择--</option>
{% for i in data %}
<option value='{{ i.id }}' >{{ i.name }}</option>
{% endfor %}
</select>
<script src='/static/js/jq.js' ></script>
<script>
// 获取所有的select
$('select').live('change',function(){
var id = $(this).val();
// 清楚后面的杂质元素
$(this).nextAll().remove();
// 发送ajax请求
$.get("{% url 'getcity' %}",{'id':id},function(data){
// 判断data是否有数据
if (data.length==0){return};
var sel = $('<select></select>');
var ops = '<option>--请选择--</option>';
for (var i=0;i<data.length;i++){
ops += '<option value='+data[i].id+' >'+data[i].name+'</option>';
};
// opd插入到sel
sel.html(ops);
// sel追加
$('body').append(sel);
},'json')
})
</script>
# 配置文件设置静态文件的路径
STATIC_URL = '/static/'
STATICFILES_DIRS = [
os.path.join(BASE_DIR,'static'),
]
template模板
配置模板引擎—seeting.py
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [os.path.join(BASE_DIR,'templates')], # 主要是这里,配置模板的路径
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
],
},
},
]
常用模板语法
-
变量
-
变量输出
{{ var }}
-
注意:
- 变量数据来源是后台对模板的解析以及数据分配
- 变量命名规范
- var.avr.var解析为:
- 字典解析
- 对象属性解析
- 索引解析
- 变量如果不存在,自动插入空字符串
- 模板中调用方法不能传递参数
-
-
标签语法
{% tag %}
-
作用:
- 动态创建文本
- 循环或者流程控制
- 加载外部模板
-
for 标签
{% for i in arr %} {% endfor %}
-
if 分支结构
{% if ... %} {% elif... %} {% else %} {% endif %}
-
comment多行注释标签
{% comment %} {% endcomment %}
-
include标签 加载模板,并且以标签内参数进行渲染
{% include 'base/index.html' %}
-
url 反向解析
{% url 'urlname' %}
-
csrf 跨站请求
{% chrf_token %}
-
过滤器
{{ var|uppr }} {{ 变量名|过滤器 }}
{{ HTML|safe }} 关闭html安全转译
{% if list1|length>1 %} 结合if标签使用
{{ name|lower|upper }} 过滤器的串联使用
{{ list|join:',' }} 过滤器传递参数 使用''引起来
{{ value|default:'默认值' }} 在变量空值或者False的时候返回默认值
{{ value|date:'Y-m-d H:M:s' }} 格式化显示时间
模板运算 不太好用
{{ value|add:10 }} +10
{{ value|add:-10 }} -10
{% widthratio 5 1 100 %} 5 × 100
{% widthratio 5 100 1 %} 5 ÷ 100
自定义标签个自定义过滤器
创建一个templatetags的目录【创建在定义的app目录中】
在这个目录中创建一个pagetag.py文件----文件名自定义
内容:
from django import template
register = template.Library()
# 自定义过滤器
@register.filter
def my_upper(val):
print(val,'应用了一次自定义的过滤器')
return val.upper()
# 自定义标签
from django.utils.html import format_html
@register.simple_tag
def jiafa(a,b):
res = int(a) + int(b)
return res
使用自定义的过滤器和标签
首先将定义的文件导入到当前的文档之中
{% load pagetag %}
<ul>
<li>使用自定义的过滤器:{{ val|my_upper }}</li>
<li>使用自定义的标签:{% jiafa 10 20 %}</li>
</ul>
文档片段的重复引用
- 在templates目录中创建include目录,用来存重复使用的文档片段
- 目录中的每一个html文件是一个代码片段
- 在文档之中使用{% includ ‘xxx.htm’ %}就可以将片段导入此文档
模板的继承
- 减少页面内容重复定义,同一段内容多次使用
- 直观的是网站的头和尾两个部分,定义在父模板中,子模板继承使用
- 在这里会用到block标签,预留在父模板中,以便子模板插入自己的内容
- 父模板是放在templates目录下你的extends目录之中
- 在此目录中创建父模板base.html
定义在父模板中的block预留位置
{% block block_name %}
可以在这里定义默认值
如果不定义,默认空字符串
{% endblock %}
子模板 导入父模板 并且在预留位置插入内容
{% extends 'base.html' %} 导入模板的位置,在文档头部
{% block block_name %}
<ul>
<li>插入了自己的内容</li>
</ul>
{% endblock %}