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 多对多创建方式的更多相关文章

  1. django基础之day09,多对多创建数据表的三种方式

    多对多三种创建方式 1.全自动(用在表关系不复杂的一般情况) class Book(models.Model): title=models.CharField(max_length=32) 多对多关系 ...

  2. 2019年6月14日 Web框架之Django_07 进阶操作(MTV与MVC、多对多表三种创建方式、前后端传输数据编码格式contentType、ajax、自定义分页器)

    摘要 MTV与MVC 多对多表三种创建方式 ajax ,前后端传输数据编码格式contentType 批量插入数据和自定义分页器 一.MVC与MTV MVC(Model View Controller ...

  3. Django多对多表的三种创建方式,MTV与MVC概念

    MTV与MVC MTV模型(django): M:模型层(models.py) T:templates V:views MVC模型: M:模型层(models.py) V:视图层(views.py) ...

  4. Django之ORM多对多表创建方式,AJAX异步提交,分页器组件等

    MTV与MVC MTV模型: ​ M:模型层(models.py),负责业务对象和数据库关系的映射(ORM) ​ T:模板层(Template),负责如何把页面展示给用户(HTML) ​ V:视图层( ...

  5. ORM中choices参数(重要)、MTV于MVC模型、多对多关系三种创建方式

    choices参数(重要) **使用方式

  6. dya49:django:wsgrief&模板渲染Jinjia2&django的MTV/MVC框架&创建/启动一个django项目

    目录 1.自定义web框架wsgiref版 2.自定义web框架wsgiref版-优化版 3.模板渲染JinJa2 4.MTV和MVC框架 5.django:下载安装&创建启动 自定义web框 ...

  7. orm查询优化 MTV和MVC模型 字段的chioces参数 Ajax

    目录 一.ORM查询优化 1. all()查询 2. only()/defer()方法 (1)only()方法 (2)defer()方法 3. select_related()/prefetch_re ...

  8. django----orm查询优化 MTV与MVC模型 choice参数 ajax serializers

    目录 orm查询优化 only defer select_related 与 prefetch_related MTV 与 MVC 模型 choice参数 Ajax 前端代码 后端代码 前后端传输数据 ...

  9. Django-choices字段值对应关系(性别)-MTV与MVC科普-Ajax发json格式与文件格式数据-contentType格式-Ajax搭配sweetalert实现删除确认弹窗-自定义分页器-批量插入-07

    目录 models 字段补充 choices 参数/字段(用的很多) MTV与MVC模型 科普 Ajax 发送 GET.POST 请求的几种常见方式 用 Ajax 做一个小案例 准备工作 动手用 Aj ...

随机推荐

  1. ACM之路(13)—— 树型dp

    最近刷了一套(5题)的树型dp题目:http://acm.hust.edu.cn/vjudge/contest/view.action?cid=116767#overview,算是入了个门,做下总结. ...

  2. 1.7 JAVA异常总结

    1.7 JAVA异常总结 异常有的是因为用户错误引起,有的是程序错误引起的,还有其它一些是因为物理错误引起的. 三种异常:分别为检查性异常(一般异常).运行时异常(非检查性异常).错误 Throwab ...

  3. shell编程之 ()[] {}

    shell脚本中各种括号的区别以及用法 2018年08月19日 14:55:33 M_QiJunChao 阅读数:273   最近学到了shell脚本编程,觉得脚本中的不同括号有不同的用处,以及有些括 ...

  4. logserver 日志服务项目发布

    logserver是使用logback.light-4j.commons-exec等构建的简单日志服务,参考项目logbackserver和light4j,支持跟踪日志.分页查看.搜索定位.下载文件等 ...

  5. 【零基础】Selenium:Webdriver图文入门教程java篇(附相关包下载)

    一.selenium2.0简述 与一般的浏览器测试框架(爬虫框架)不同,Selenium2.0实际上由两个部分组成Selenium+webdriver,Selenium负责用户指令的解释(code), ...

  6. RDP连接失败的解决方法

    当RDP某一桌面时,远程桌面连接提示:发生身份验证错误,要求的函数不受支持. 解决方法: 打开Run, 输入gpedit.msc,打开组策略编辑器. 如上如所示,修改配置加密Oracle修正策略. E ...

  7. 转载: Windows下两种iocp实现的差距

    转自:http://blog.csdn.net/oldworm/article/details/6171430 之前几天说过,因为经典iocp实现(以下简称经典实现)多个io线程绑定在一个iocp上, ...

  8. koa 项目实战(八)生成token

    1.安装模块 npm install jsonwebtoken --save 2.引用 const jwt = require('jsonwebtoken'); ... // 返回token cons ...

  9. ajax修改表单的值后dom没更新的解决办法

    添加一个扩展方法,通过$("#id").html($("#id").formhtml())更改. 扩展方法: (function ($) { var oldHT ...

  10. python之scrapy爬取数据保存到mysql数据库

    1.创建工程 scrapy startproject tencent 2.创建项目 scrapy genspider mahuateng 3.既然保存到数据库,自然要安装pymsql pip inst ...