第六章Django
web应用程序
server端建立socket,不断地accept,当收到客户端连接信号之后,服务端向客户端发送数据,将html网页打开,read出来,并发送至客户端,这样客户端就可以浏览到网页的内容
http协议:
包头里面的数据用 一个“\r\n”来区分,最后使用两个“\r\n”来区分数据
GET协议把数据放在了包头里面,POST协议把数据放在包头的最后面
GET提交的数据以“?”区分,参数之间以“&”进行连接
相应格式:
协议版本 状态码 状态码的原因短语 相应首部字段 主体
web框架 yuan功能总结 main.py: 启动文件,封装了socket 1 urls.py: 路径与视图函数映射关系 ---- url控制器 2 views.py 视图函数,固定有一个形式参数:environ -----视图函数, 3 templates文件夹: html文件 -----模板 4 models: 在项目启动前,在数据库中创建表结构 ----- 与数据库相关 Django的安装与启动
创建应用:python manage.py startapp blog
urlpatterns = [
re_path(r'^articles/2003/$', views.special_case_2003),
re_path(r'^articles/([0-9]{4})/$', views.year_archive),
re_path(r'^articles/([0-9]{4})/([0-9]{2})/$', views.month_archive),
re_path(r'^articles/([0-9]{4})/([0-9]{2})/([0-9]+)/$', views.article_detail),
]
有名分组:在组前面加上?P<组名> 即可,在传参时的形参必须是“组名”,否则会出错
命名空间:namespace
app01.urls:
需要加上
app_name = "app01"
urlpatterns=[
re_path(r'^index/',views.index,name="index"),
] 同理在ap02.urls加上相同的配置 views.py:
def index(request):
return HttpResponse(reverse("app01:index"))
需要加上反向解析 注册自定义转换器
先建一个类
class FourDigitYearConverter:
regex = '[0-9]{2}' #正则表达式的公式 def to_python(self,value):
return int(value) def to_url(self,value):
return '%04d' % value
在项目中注册转换器
# 注册定义的url转换器
register_converter(FourDigitYearConverter,'mm') #FourDigitYearConverter : 为以上类名
之后在urls里可以直接path使用
path('articles/<mm:month>/',views.month_archive)
模板语法 只有两个
1.{{}}
可以在
return render(request,'index.html',locals()) 这样就把该函数里的全部全局变量都传过去了
同时在index.html可以通过 . 来过去数据 如一个数组l=【‘123’,‘456’,‘789’】 ,在html可以通过l.2 获取到数据456
2{%%}
{%if%} {%endif%} 自定义标签与过滤器
1.在settings的INSTALLED_APPS加上当前app的名称,不然django无法找到自定义的simple_tag.
2.在app文件夹里面添加templatetags模块(模块名只能是templatetags)
3.在templatetags里面创建任意py文件
4.在该py文件里面引入
from django import template
register = template.Library() # 固定名字
@register.filter #加上装饰器,这个为模板过滤器
def filter_multi(x,y):
return x*y @register.simple_tag #标签过滤器
def filter_tag(x,y):
return x*y
5.在html文件里面读取该过滤器
{%load py的文件名%}
6.使用
{{ 2 | filter_multi:5 }} {% filter_tag 5 6 %}
继承:extends
在一个base.html 里面把模板写好
在另一个html里面引入base.html
{% extends "base.html" %}
这时候可以在下面继续添加block里面的内容
{{% block title %}
<title>第一个</title>
{% endblock title%}
模型层ORM
ORM 对象-关系-映射
通过编写ORM层,控制pysql转换成db语句,再去控制db数据库。py文件里面通过创建一个类 生成表模型
1.创建模型
from django.db import models # Create your models here. class Book(models.Model):
id = models.AutoField(primary_key=True)
title=models.CharField(max_length=32)
state=models.BooleanField()
pub_date=models.DateField()
price=models.DecimalField(max_digits=8,decimal_places=2)
publish=models.CharField(max_length=32)
创建一个app,然后在app项目文件下的models下创建类
2.配置链接数据库settings
在项目文件下的settings文件设置下,设置数据库信息
DATABASES = {
'default':{
'ENGINE':'django.db.backends.mysql',
'NAME':'bms', #创建数据库名字
'USER':'root', #链接数据库用户名
'PASSWORD':'', #链接数据库密码
"HOST":'127.0.0.1', #目标数据库地址
'PORT':3306 #目标数据库端口
}
}
3.确认信息
①在项目app文件下的__init__插入代码:
import pymysql pymysql.install_as_MySQLdb()
②确保配置文件中的INSTALLED_APPS中写入我们创建的app名称
如在installed_apps 下添加app文件名 最后,可以进行数据迁移
python manage.py makemigrations
python manage.py migrate
数据库的建立create:
方式一:
book_obj = Book.objects.create(title='第一个数据库',state=True,price=500,pub_date="2012-12-12",publish='人民出版社') #里面的数据格式需要与建立时的数据格式一致 方式二:
book_obj = Book(title='方式二',publish='机械出版社',state=True,pub_date="2010-12-11",price=10.12)
book_obj.save() #需要多一个save
查询表:
Django 自己生成的一个数据对象:QuerySet: [obj1,obj2,obj3....]
可以通过语句Book.object ---> 生成QuerySet数据
Book.object.all() 可以读取所有的数据
values方法: 返回和调用都是QuerySet
book_obj = Book.objects.values('price')
相当于
list = []
for obj in QuerySet:
list.append{'price':obj['price']}
.... #如果在values后面加值,就继续append values_list方法: 返回和调用都是QuerySet
book_obj = Book.objects.values_list('price')
distinct:去重 从返回结果中剔除重复纪录 表的查询 一对多的查询:
A---B
如果关联表在A表中:
A----->B :正向查询
反过来通过B去查A 则是反向查询,主要看关联表在哪张表里面
正向查询:看字段
反向查询:看表名:表名小写__set.all() 聚合与分组查询
关键字:annotate
总结 跨表的分组查询的模型:
# 每一个后表模型.objects.values("pk").annotate(聚合函数(关联表__统计字段))
AJAX
特点:
1.使用JavaScript向服务器发送异步请求
2.局部刷新
$(".Ajax").click(function () {
$.ajax({
url:"/test_ajax/", //请求地址
type:"get", //请求的类型poet或者是get
success:function (data) {
$(".haha").html(data)
console.log(data)
}
})
}) 数据之间的传输 通过使用json序列化
在py里面使用json.dump序列化
在Ajax里面使用JSON.parse 反序列化进行解析 利用Form表单进行文件上传
def file_put(request):
if request.method=="POST":
print('')
print(request.POST)
print(request.FILES) file_obj = request.FILES.get("tou") with open(file_obj.name,'wb') as f:
for i in file_obj:
f.write(i) return HttpResponse('OK') return render(request, "file_put.html")
批量导入数据库的数据:
'''
批量导入数据: Booklist=[]
for i in range(100):
book = Book(user="book_%s"%i,pwd=i*i)
Booklist.append(book)
Book.objects.bulk_create(Booklist)
'''
分页器:
book_list = Book.objects.all() paginator = Paginator(book_list,10) print("count:", paginator.count) # 数据总数
print("num_pages", paginator.num_pages) # 总页数
print("page_range", paginator.page_range) # 页码的列表 page1=paginator.page(4) #第4页的page对象数据
for i in page1: #遍历
print(i) print(page1.object_list) #直接拿出该page的所有对象
#捕捉EmptyPage错误信息时做的处理
try:
current_page = int(request.GET.get("page",1))
page1 = paginator.page(current_page)
except EmptyPage as e:
page1 = paginator.page(1)
print(page2.has_next()) #是否有下一页
print(page2.next_page_number()) #下一页的页码
print(page2.has_previous()) #是否有上一页
print(page2.previous_page_number()) #上一页的页码
form组件
form.is_valid() #:返回布尔值
form.cleaned_data #:{"name":"yuan","email":"123@qq.com"} 返回匹配成功的字典
form.errors #返回对应类字段的错误信息 :{"name":[".........."]}
from django.forms import widgets
class UserForm(forms.Form): #用于认证用
name = forms.CharField(max_length=32,label="用户名", widget=widgets.TextInput(attrs={"class":"form-control"}),error_messages={“required”:“该字段不能为空”}) #attr即为修改样式,error_message修改默认的错误信息,必须为required这个键名
pwd = forms.CharField(min_length=4)
r_pwd = forms.CharField(min_length=4)
email = forms.CharField()
tel = forms.CharField(min_length=4,max_length=32) def form_test(request):
if request.method == 'POST':
form = UserForm(request.POST)
if form.is_valid(): #校验是否验证通过,同时会把错误、正确的信息放在两个字典里面
print(form.cleaned_data)
else:
print(form.cleaned_data)
print(form.errors) # ErrorDict : {"校验错误的字段":["错误信息",]}
print(form.errors.get("name")) # ErrorList ["错误信息",]
return HttpResponse("OK")
form = UserForm()
return render(request, "form_test.html", locals()) form = UserForm() return render(request,"form_test.html")
在html里面想打印错误信息,可以{{form.name.errors}} 这样可以获取name里的错误信息
利用form表单组件 进行文件上传,使用FormData
$(".login_btn").click(function () {
var form_data = new FormData(); //首先实例化一个FormData
form_data.append("user",$("#id_user").val()) //再往里面添加数据
form_data.append("pwd",$("#id_pwd").val())
form_data.append("r_pwd",$("#id_r_pwd").val())
form_data.append("email",$("#id_email").val())
form_data.append("img",($("#avater")[0].files[0])) //该为文件,主要是传它才使用FormData,不然不用这么麻烦
form_data.append("csrfmiddlewaretoken",$("[name='csrfmiddlewaretoken']").val()) $.ajax({
url:"",
type:"post",
contentType:false, //必须设置这两个值
processData:false,
data:form_data, //最后把这个对象传给data
success:function (data) {
console.log(data)
}
})
})
局部钩子
在规则里面class 添加一个方法"clean_%s"name
def clean_tel(self):
val = self.cleaned_data.get('tel') if len(val) == 11:
return val
else:
raise ValidationError("手机号格式错误")
form.is_valid--》self.errors-->self.full_clean--》self._clean_fields()
依次校验每个字段,之后再走钩子去判断里面有没有clean_%s 用户自定义的方法
if hasattr(self, 'clean_%s' % name):
value = getattr(self, 'clean_%s' % name)()
self.cleaned_data[name] = value
全局钩子
def clean(self):
pwd = self.cleaned_data.get('pwd')
r_pwd = self.cleaned_data.get('r_pwd') if pwd and r_pwd:
if pwd == r_pwd:
return self.cleaned_data
else:
raise ValidationError('两次密码不一致!')
else:
return self.cleaned_data
视图函数 form_test.html
<div class="container">
<form action="" method="post">
{% csrf_token %}
<div class="row">
<div>
<p>
{{ form.name.label }}{{ form.name }}<span>{{ form.name.errors }}</span><span class="has-error pull-right">{{ errors.0 }}</span> #errors类 自己写
</p>
</div>
<div>
<p>
{{ form.pwd.label }}{{ form.pwd }}<span>{{ form.pwd.errors }}</span>
</p>
</div>
<div>
<p>
{{ form.r_pwd.label }}{{ form.r_pwd }}<span>{{ form.r_pwd.errors }}</span><span class="pull-right error">{{ errors.0 }}</span>
</p>
</div>
<div>
<p>
{{ form.email.label }}{{ form.email }}<span>{{ form.email.errors }}</span>
</p>
</div>
<div>
<p>
{{ form.tel.label }}{{ form.tel }}<span>{{ form.tel.errors }}</span>
</p>
</div>
<input type="submit" value="提交">
cookie:具体一个浏览器针对一个服务器存储key-value({})
获取cookie:
cookie 信息储存在request.COOKIE
第六章Django的更多相关文章
- 《Django By Example》第六章 中文 翻译 (个人学习,渣翻)
书籍出处:https://www.packtpub.com/web-development/django-example 原作者:Antonio Melé (译者注:无他,祝大家年会都中奖!) 第六章 ...
- 第二十二章 Django会话与表单验证
第二十二章 Django会话与表单验证 第一课 模板回顾 1.基本操作 def func(req): return render(req,'index.html',{'val':[1,2,3...]} ...
- 第六章、Cookies和Session
目录 第六章.Cookies和Session 一.来源 二.cookie工作原理 工作原理: 三.session的工作原理 工作原理: 四.如何操作cookie 服务端常见的cookie操作 五.案例 ...
- 第六章、forms组件
目录 第六章.forms组件 一.注册功能手写 二.forms组件完整写法 基本使用 三.forms组件前端渲染标签组件 三.forms组件其他知识点 在python console测试 校验数据 f ...
- 第六章、ajax方法以及序列化组件
目录 第六章.ajax方法 一.choice参数介绍 二.MTV与MVC模型 三.ajax方法 四.案例 五.Ajax传json格式的数据 六. AJAX传文件 代码如下 ajax传文件需要注意的事项 ...
- 精通Web Analytics 2.0 (8) 第六章:使用定性数据解答”为什么“的谜团
精通Web Analytics 2.0 : 用户中心科学与在线统计艺术 第六章:使用定性数据解答"为什么"的谜团 当我走进一家超市,我不希望员工会认出我或重新为我布置商店. 然而, ...
- 《Entity Framework 6 Recipes》中文翻译系列 (30) ------ 第六章 继承与建模高级应用之多对多关联
翻译的初衷以及为什么选择<Entity Framework 6 Recipes>来学习,请看本系列开篇 第六章 继承与建模高级应用 现在,你应该对实体框架中基本的建模有了一定的了解,本章 ...
- 《Entity Framework 6 Recipes》中文翻译系列 (37) ------ 第六章 继承与建模高级应用之独立关联与外键关联
翻译的初衷以及为什么选择<Entity Framework 6 Recipes>来学习,请看本系列开篇 6-13 在基类中应用条件 问题 你想从一个已存在的模型中的实体派生一个新的实体, ...
- KnockoutJS 3.X API 第六章 组件(5) 高级应用组件加载器
无论何时使用组件绑定或自定义元素注入组件,Knockout都将使用一个或多个组件装载器获取该组件的模板和视图模型. 组件加载器的任务是异步提供任何给定组件名称的模板/视图模型对. 本节目录 默认组件加 ...
随机推荐
- bash循环
bash脚本-循环02 bash脚本编程:循环 执行流程: 1.顺序执行 2.选择执行:if 3.循环执行:for,while,until 1.循环执行的条件 进入条件: for:列表元素非空 w ...
- jmeter遇到问题及解决办法
1.要得到前一个sampler的响应信息,是加beanshell sampler 还是加beanshell postprocessor? 答:在http取样器后添加beanshell sample ...
- Python条件判断 if-else for循环 while循环 break continue
条件判断 if-else if-else语句是通过if 后面的是否为真,当为True,就执行if代码块后面的,如果为False,同时又有else语句,执行else后面的内容.没有else,什么都不执行 ...
- 移动端click事件无反应或反应慢 touchend事件页面滑动时频繁触发
H5页面的点击事件click 无论在浏览器 iframe还是小程序里面 都会出现点击无反应或者反应慢的情况出现 所以决定用touchend事件来代替click 但是touchend事件触发比较灵敏 在 ...
- 自学python之路(day4)
一 购物车小程序 goods=[{}, {}, {}] shop_car={} li=[] ,len(goods)): li.append(i) money=input('请输入您的总金额:') if ...
- Navicat连接Mysql报错:Client does not support authentication protocol requested by server;
Navicat连接Mysql报错:Client does not support authentication protocol requested by server: 刚安装Mysql,想用Nav ...
- Groovy学习笔记-Java 5新特性支持
1.枚举enum enum CoffeeSize{ SHORT, SMALL, MEDIUM, LARGE, MUG } def orderCoffee(size){ print "Coff ...
- Linux文件属性描述
mtime -- modify time 修改时间 硬链接硬链接(hard link, 也称链接)就是一个文件的一个或多个文件名.再说白点,所谓链接无非是把文件名和计算机文件系统使用的节点号链接起来. ...
- Mybatis-基于配置文件的配置(——纪念这个即将被抛弃的孩子)
虽然内心相信Mybatis基于配置文件的配置早已经在实战之中被注解所遗忘,但是我相信还是会有一小部分人还是需要这种技术去维护原有使用这种方式去搭建的项目. 废话不多说首先使用框架包是不能少的了.导入M ...
- the shortest path algorithm
Dijkstra算法 又称迪杰斯特拉算法,是一个经典的最短路径算法,主要特点是以起始点为中心向外层层扩展,直到扩展到终点为止,使用了广度优先搜索解决赋权有向图的单源最短路径问题,算法最终得到一个最短路 ...