django ajax MTV与MVC 多对多创建方式
MTV与MVC
MTV模型(django):
M:模型层(models.py)
T:templates
V:views
MVC模型:
M:模型层(models.py)
V:视图层(views.py)
C:控制器(Controller) urls.py
本质:django的MTV也是MVC
多对多表三种创建方式
第一种 django orm自动帮我们创建
class Book(models.Model):
name = models.CharField(max_length=32)
authors = models.ManyToManyField(to='Author') class Author(models.Model):
name = models.CharField(max_length=32)
第二种纯手动创建第三张表
class Book(models.Model):
name = models.CharField(max_length=32) class Author(models.Model):
name = models.CharField(max_length=32) class Book2Author(models.Model):
book = models.ForeignKey(to='Book')
author = models.ForeignKey(to='Author')
info = models.CharField(max_length=32)
第三种半自动创建第三张表(可扩展性高,并且能够符合orm查询) ps:半自动不支持多对多字段的增删改查方法 add(),set(),remove(),clear()
class Book(models.Model):
name = models.CharField(max_length=32) #第三种创建表的方式
authors = models.ManyToManyField(to='Author',through='Book2Author',through_fields('book','author'))
#through_fields book 字段放前面 class Author(models.Model):
name = models.CharField(max_length=32)
#book = models.ManyToManyField(to='Book',through='Book2Author',through_fields('author','book'))
#through_fields author 字段放前面 class Book2Author(models.Model):
book = models.ForeignKey(to='Book')
author = models.ForeignKey(to='Author')
info = models.CharField(max_length=32)
foreignkey字段在表中默认加_id (Book2Author >>>book_id)
前后端传输数据编码格式contentType
1 urlencoded(form表单与ajax默认的数据提交编码格式)
#对应的数据格式:name = jason&password=66
#后端获取数据;request.POST
#ps:django会将urlencoded编码的数据解析自动放到request.POST 2 formdata 传输文件
form表单传输文件的编码格式
后端获取文件格式数据:request.FILES
后端获取普通键值对数据:request.POST form表单提交文件需要更改
默认的 enctype="application/x-www-form-urlencoded"
更改为 enctype="multipart/form-data" 3 application/json(ajax支持)
ajax发送json格式数据 将原生的二进制数据存在request.body中,让你自己手动处理
需要注意的点
编码与数据格式要一致
ajax
1 前端有哪些方式可以向后端发请求
浏览器窗口手动输入网址 get请求
a标签的href属性 get请求
form表单 get/post请求(默认是get请求)
ajax get/post请求
stringify与parse方法:
JSON.parse():用于将JSON字符串转换为JavaScript读写(json只认双引的字符串格式) JSON.stringify():用于将JavaScript值转换为JSON字符串
2 ajax特点:
异步提交
局部刷新
3 ajax基本语法
提交的地址(url) 不写默认往当前当前位置提交
提交的方式(type)
提交的数据(data)
回调函数(success)
$('#d1').click(function(){
$.ajax({
//提交的地址
url:'/index/',
//提交的方式
type:'post',
//提交的数据
data:{'name':'jason','password':''},
//回调函数
success:function(data){ //data接收的就是异步提交返回的结果
alert(data)
}
})
})
4 ajax默认传输数据的编码格式也是urlencoded
5 前后端传输数据,你不能骗人家,数据是什么格式就应该告诉别人是什么格式(数据与编码要一一对应)
ajax传输json格式数据
$('#d1').click(function () {
$.ajax({
url:'', // url参数可以不写,默认就是当前页面打开的地址
type:'post',
contentType:'application/json',
data:JSON.stringify({'name':'jason','hobby':'study'}),
success:function (data) {
{#alert(data)#}
{#$('#i3').val(data)#}
}
})
});
后端:data = request.body #只有json才可以看body
res = data.decode('utf-8')
res2 =json.loads(res)
#这个是后端查看字典 但是不能json序列化 $('#d1').click(function () {
$.ajax({
url: '/index/',
type:'post',
data:{'name':'jason','password':'123'},
success:function (data) {
alert(data)
}
})
})
前端 发送字符串类型的字典
# 这个只能看字典不能序列化
# def index(request):
# # print(request.POST)
# # print(request.FILES)
# if request.method == 'POST':
# # print(request.POST) #<QueryDict: {'name': ['德云色'], 'password': ['12344555']}>
# # print(request.FILES) #<MultiValueDict: {'myfile': [<InMemoryUploadedFile: 3.png (image/png)>]}>
#
# print(request.body) # 想要查看前端发来的字典 b'name=jason&password=123'
#
# return HttpResponse('收到了 老弟')
# return render(request,'index.html')
对应后端
<input type="text" id="i1">+<input type="text" id="i2">=<input type="text" id="i3">
<input type="file" name="myfile" id="i1">
<button id="d1">加我加我~</button> <script> {#这个是1+1那个#}
$('#d1').click(function () {
$.ajax({
url:'',
type:'post',
contentType:'application/json',
data:JSON.stringify({'name':'jason','hobby':'study'}),
success:function (data) {
alert(data)
$('#i3').val(data)
}
})
})
前端 内容输入框
def index(request): if request.method == 'POST':
print(request.body)
import json
data =request.body
print(data)
res1 = data.decode('utf-8')
print(res1,type(res1)) res2 = json.loads(res1)
print(res2,type(res2)) i1 = request.POST.get('i1')
i2 = request.POST.get('i2') print(i1,i2)
# res = int(i1) + int(i2)
# print(res,type(res)) return HttpResponse('收到了 老弟')
return render(request,'index.html')
后端
ajax传输文件
$('#d1').click(function(){
let formdata = new FormData();
//FormData对象不仅仅可以传文件还可以传普通的键值对
formdata.append('name','jason');
//获取input框存放的文件
//$('#i1')[0].files[0]
formdata.append('myfile',$('#i1')[0].files[0]); 获取input框存储的文件数据$('input'[type="file"]')[0].files[0]
$.ajax({
url:'',
type:'post',
data:formdata,
//ajax发送文件需要修改两个固定的参数
processData:false, //告诉浏览器不要处理我的数据
contentType:false, //不要用任何的编码,就用我formdata自带的编码格式,django能够自动识别该formdata对象
// 回调函数
success:function(data){
alert(data)
}
})
});
form表单与ajax异同点
1 form表单不支持与不提交局部刷新
2 form表单不支持传输json格式数据
3 form表单与ajax默认传输数据的编码格式都urlencoded
批量插入数据
l = []
for i in range(10000):
l.append(models.Book2(name='第%s本书'%i)) #不走数据库
models.Book2.objects.bulk_create(l) #批量插入数据
补充:<li><a href='?page=1'>1</a></li> 自动补全当前路径
自定义分页器:
页码的渲染通常都是单数
需要完善的
1 加首页和尾页
2 页码的个数应该是固定的
自定义分页器的使用
后端:
book_list = models.Book2.objects.all() #数据总条数
all_count = book_list.count() #当前页
current_page = request.GET.get('page',1) #实例一个分液器对象
page_obj = my_page.Pagination(current_page=current_page,all_count=all_count) #对总数据进行切片
page_queryset = book_list[page_obj.start:page_obj.end]
前端:
<table class="table table-hover table-bordered table-striped">
<thead>
<tr>
<th>id</th>
<th>name</th>
</tr>
</thead>
<tbody>
{% for book in page_queryset %}
<tr>
<td>{{ book.pk }}</td>
<td>{{ book.name }}</td>
</tr>
{% endfor %}
</tbody>
</table>
{{ page_obj.page_html|safe }}
{{ page_obj.page_html|safe }} #帮你渲染的是带有bootstrap样式的分页器
自定义分页器
class Pagination(object):
def __init__(self, current_page, all_count, per_page_num=2, pager_count=11):
"""
封装分页相关数据
:param current_page: 当前页
:param all_count: 数据库中的数据总条数
:param per_page_num: 每页显示的数据条数
:param pager_count: 最多显示的页码个数 用法:
queryset = model.objects.all()
page_obj = Pagination(current_page,all_count)
page_data = queryset[page_obj.start:page_obj.end]
获取数据用page_data而不再使用原始的queryset
获取前端分页样式用page_obj.page_html
"""
try:
current_page = int(current_page)
except Exception as e:
current_page = 1 if current_page < 1:
current_page = 1 self.current_page = current_page self.all_count = all_count
self.per_page_num = per_page_num # 总页码
all_pager, tmp = divmod(all_count, per_page_num)
if tmp:
all_pager += 1
self.all_pager = all_pager self.pager_count = pager_count
self.pager_count_half = int((pager_count - 1) / 2) @property
def start(self):
return (self.current_page - 1) * self.per_page_num @property
def end(self):
return self.current_page * self.per_page_num def page_html(self):
# 如果总页码 < 11个:
if self.all_pager <= self.pager_count:
pager_start = 1
pager_end = self.all_pager + 1
# 总页码 > 11
else:
# 当前页如果<=页面上最多显示11/2个页码
if self.current_page <= self.pager_count_half:
pager_start = 1
pager_end = self.pager_count + 1 # 当前页大于5
else:
# 页码翻到最后
if (self.current_page + self.pager_count_half) > self.all_pager:
pager_end = self.all_pager + 1
pager_start = self.all_pager - self.pager_count + 1
else:
pager_start = self.current_page - self.pager_count_half
pager_end = self.current_page + self.pager_count_half + 1 page_html_list = []
# 添加前面的nav和ul标签
page_html_list.append('''
<nav aria-label='Page navigation>'
<ul class='pagination'>
''')
first_page = '<li><a href="?page=%s">首页</a></li>' % (1)
page_html_list.append(first_page) if self.current_page <= 1:
prev_page = '<li class="disabled"><a href="#">上一页</a></li>'
else:
prev_page = '<li><a href="?page=%s">上一页</a></li>' % (self.current_page - 1,) page_html_list.append(prev_page) for i in range(pager_start, pager_end):
if i == self.current_page:
temp = '<li class="active"><a href="?page=%s">%s</a></li>' % (i, i,)
else:
temp = '<li><a href="?page=%s">%s</a></li>' % (i, i,)
page_html_list.append(temp) if self.current_page >= self.all_pager:
next_page = '<li class="disabled"><a href="#">下一页</a></li>'
else:
next_page = '<li><a href="?page=%s">下一页</a></li>' % (self.current_page + 1,)
page_html_list.append(next_page) last_page = '<li><a href="?page=%s">尾页</a></li>' % (self.all_pager,)
page_html_list.append(last_page)
# 尾部添加标签
page_html_list.append('''
</nav>
</ul>
''')
return ''.join(page_html_list)
分页器
importlib模块
import importlib
s = 'xxx.b'
res = importlib.import_module(s)
会将s变成 form xxx import b
django ajax MTV与MVC 多对多创建方式的更多相关文章
- django基础之day09,多对多创建数据表的三种方式
多对多三种创建方式 1.全自动(用在表关系不复杂的一般情况) class Book(models.Model): title=models.CharField(max_length=32) 多对多关系 ...
- 2019年6月14日 Web框架之Django_07 进阶操作(MTV与MVC、多对多表三种创建方式、前后端传输数据编码格式contentType、ajax、自定义分页器)
摘要 MTV与MVC 多对多表三种创建方式 ajax ,前后端传输数据编码格式contentType 批量插入数据和自定义分页器 一.MVC与MTV MVC(Model View Controller ...
- Django多对多表的三种创建方式,MTV与MVC概念
MTV与MVC MTV模型(django): M:模型层(models.py) T:templates V:views MVC模型: M:模型层(models.py) V:视图层(views.py) ...
- Django之ORM多对多表创建方式,AJAX异步提交,分页器组件等
MTV与MVC MTV模型: M:模型层(models.py),负责业务对象和数据库关系的映射(ORM) T:模板层(Template),负责如何把页面展示给用户(HTML) V:视图层( ...
- ORM中choices参数(重要)、MTV于MVC模型、多对多关系三种创建方式
choices参数(重要) **使用方式
- dya49:django:wsgrief&模板渲染Jinjia2&django的MTV/MVC框架&创建/启动一个django项目
目录 1.自定义web框架wsgiref版 2.自定义web框架wsgiref版-优化版 3.模板渲染JinJa2 4.MTV和MVC框架 5.django:下载安装&创建启动 自定义web框 ...
- orm查询优化 MTV和MVC模型 字段的chioces参数 Ajax
目录 一.ORM查询优化 1. all()查询 2. only()/defer()方法 (1)only()方法 (2)defer()方法 3. select_related()/prefetch_re ...
- django----orm查询优化 MTV与MVC模型 choice参数 ajax serializers
目录 orm查询优化 only defer select_related 与 prefetch_related MTV 与 MVC 模型 choice参数 Ajax 前端代码 后端代码 前后端传输数据 ...
- Django-choices字段值对应关系(性别)-MTV与MVC科普-Ajax发json格式与文件格式数据-contentType格式-Ajax搭配sweetalert实现删除确认弹窗-自定义分页器-批量插入-07
目录 models 字段补充 choices 参数/字段(用的很多) MTV与MVC模型 科普 Ajax 发送 GET.POST 请求的几种常见方式 用 Ajax 做一个小案例 准备工作 动手用 Aj ...
随机推荐
- ACM之路(13)—— 树型dp
最近刷了一套(5题)的树型dp题目:http://acm.hust.edu.cn/vjudge/contest/view.action?cid=116767#overview,算是入了个门,做下总结. ...
- 1.7 JAVA异常总结
1.7 JAVA异常总结 异常有的是因为用户错误引起,有的是程序错误引起的,还有其它一些是因为物理错误引起的. 三种异常:分别为检查性异常(一般异常).运行时异常(非检查性异常).错误 Throwab ...
- shell编程之 ()[] {}
shell脚本中各种括号的区别以及用法 2018年08月19日 14:55:33 M_QiJunChao 阅读数:273 最近学到了shell脚本编程,觉得脚本中的不同括号有不同的用处,以及有些括 ...
- logserver 日志服务项目发布
logserver是使用logback.light-4j.commons-exec等构建的简单日志服务,参考项目logbackserver和light4j,支持跟踪日志.分页查看.搜索定位.下载文件等 ...
- 【零基础】Selenium:Webdriver图文入门教程java篇(附相关包下载)
一.selenium2.0简述 与一般的浏览器测试框架(爬虫框架)不同,Selenium2.0实际上由两个部分组成Selenium+webdriver,Selenium负责用户指令的解释(code), ...
- RDP连接失败的解决方法
当RDP某一桌面时,远程桌面连接提示:发生身份验证错误,要求的函数不受支持. 解决方法: 打开Run, 输入gpedit.msc,打开组策略编辑器. 如上如所示,修改配置加密Oracle修正策略. E ...
- 转载: Windows下两种iocp实现的差距
转自:http://blog.csdn.net/oldworm/article/details/6171430 之前几天说过,因为经典iocp实现(以下简称经典实现)多个io线程绑定在一个iocp上, ...
- koa 项目实战(八)生成token
1.安装模块 npm install jsonwebtoken --save 2.引用 const jwt = require('jsonwebtoken'); ... // 返回token cons ...
- ajax修改表单的值后dom没更新的解决办法
添加一个扩展方法,通过$("#id").html($("#id").formhtml())更改. 扩展方法: (function ($) { var oldHT ...
- python之scrapy爬取数据保存到mysql数据库
1.创建工程 scrapy startproject tencent 2.创建项目 scrapy genspider mahuateng 3.既然保存到数据库,自然要安装pymsql pip inst ...