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. jQuery的$符号

    jQuery使用$的原因是: 书写简洁, 相对于其他字符与众不同, 容易被记住. JQuery占用了两个变量: $ 和 jQuery. 当在代码中打印 $ 和 jQuery时: <script ...

  2. Codeforces 959D. Mahmoud and Ehab and another array construction task(构造, 简单数论)

    Codeforces 959D. Mahmoud and Ehab and another array construction task 题意 构造一个任意两个数都互质的序列,使其字典序大等于a序列 ...

  3. Explain详解

    explain语句用于查看某个查询语句具体使用了什么执行计划 执行输出各列详解 table 每条记录对应一个表的查询,如果是两表连接查询,就会有两条记录,table对应查询表名 id 查询语句可能是单 ...

  4. 常用css模板

    段落超出显示省略号(可单行多行) .p-content{ overflow:hidden; text-overflow:ellipsis; display:-webkit-box; -webkit-b ...

  5. Python 寻找文件夹里以特定格式结尾的文件

    代码: import os, re, time name = 'linuxday01' flags = True# 文件夹bi_test中的文件列表 print os.listdir('E:\\bi_ ...

  6. shell 基数数值方法

    shell 下获取数值的结果 1. # expr 1 "+" 2 2. # echo "1+2" |bc 3. # echo $(( 1+3))

  7. springboot批量读取参数映射到实体类

    spring读取配置参数可以通过${name}的方式获取,如properties文件中存在如下配置 person.username=xi 则可通过${person.username}获取其对应的值xi ...

  8. 前端知识点回顾——Nodejs

    Node.js 事件循环机制 setImmediate()是将事件插入到事件队列尾部,主线程和事件队列的函数执行完成之后立即执行setImmediate指定的回调函数,和setTimeout(fn,0 ...

  9. hibernate一对一映射

    package loaderman.c_one2one; // 身份证 public class IdCard { // 身份证号(主键) private String cardNum;// 对象唯一 ...

  10. CSS三角形的实现原理及运用

    原理 css盒模型 一个盒子包括: margin+border+padding+content– 上下左右边框交界处出呈现平滑的斜线. 利用这个特点, 通过设置不同的上下左右边框宽度或者颜色可以得到小 ...