django ajax MTV与MVC 多对多创建方式

时间:2022-01-17 20:01:08

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中,让你自己手动处理
需要注意的点
编码与数据格式要一致

django  ajax MTV与MVC  多对多创建方式django  ajax MTV与MVC  多对多创建方式django  ajax MTV与MVC  多对多创建方式

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