博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Django之ORM多对多表创建方式,AJAX异步提交,分页器组件等
阅读量:5146 次
发布时间:2019-06-13

本文共 13069 字,大约阅读时间需要 43 分钟。

MTV与MVC

MTV模型:

​ M:模型层(models.py),负责业务对象和数据库关系的映射(ORM)

​ T:模板层(Template),负责如何把页面展示给用户(HTML)

​ V:视图层(views.py),负责业务逻辑,并在适当的时候调用Model和Template

MVC模型:

​ Web服务器开发领域里著名的MVC模式,所谓MVC就是把Web应用分为模型(M),控制器(C)和视图(V)三层,他们之间以一种插件式的、松耦合的方式连接在一起,模型负责业务对象与数据库的映射(ORM),视图负责与用户的交互(页面),控制器接受用户的输入调用模型和视图完成用户的请求。

​ M:模型层(models.py)

​ V:视图层(views.py)

​ C:控制层(Controller) urls.py

多对多表的三种创建方法

第一种自动创建第三张表

# 多对多表三种创建方式    # 1.第一种 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)        # 2.第二种纯手动创建第三张表            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)        # 3.第三种半自动创建第三张表(可扩展性高,并且能够符合orm查询)        class Book(models.Model):            name = models.CharField(max_length=32)            # 第三种创建表的方式            authors = models.ManyToManyField(to='Author',through='Book2Author',through_fields=('book','author'))        class Author(models.Model):            name = models.CharField(max_length=32)            # book = models.ManyToManyField(to='Book',through='Book2Author',through_fields=('author','book'))        class Book2Author(models.Model):            book = models.ForeignKey(to='Book')            author = models.ForeignKey(to='Author')            info = models.CharField(max_length=32)
前后端数据传输的编码格式contentType
**u**rlencoded**    **对应的数据格式:name=jason&password=666**    **后端获取数据:request.POST**    **ps;django会将urlencoded编码的数据解析自动放到request.POST****formdata**    **form表单传输文件的编码格式**    **后端获取文件格式数据:request.FILES**    **后端获取普通键值对数据:request.POST****application/json**    **ajax发送json格式数据**    **需要注意的点**        编码与数据格式要一致**

AJAX准备知识:JSON

什么是JSON?

  • JSON指的是JavaScript对象表示方式(JavaScript Object Notation)
  • JSON是轻量级的文本数据交换格式
  • JSON独立与语言
  • JSON具有自我描述性,更易于理解
  • JSON使用JavaScript 语法来描述数据对象,但是JSON任然独立于愈合和平台,JSON解释器和JSON库支持许多不同的编程语言。

5d0347ae0063278292.png

合格的json对象(json只认识双引号字符串格式)

["one", "two", "three"]{ "one": 1, "two": 2, "three": 3 }{"names": ["张三", "李四"] }[ { "name": "张三"}, {"name": "李四"} ] 

不合格的json对象:

{ name: "张三", 'age': 32 }  // 属性名必须使用双引号[32, 64, 128, 0xFFF] // 不能使用十六进制值{ "name": "张三", "age": undefined }  // 不能使用undefined{ "name": "张三",  "birthday": new Date('Fri, 26 Aug 2011 07:13:10 GMT'),  "getName":  function() {return this.name;}  // 不能使用函数和日期对象}

stringify 与parse 方法

JavaScript 中关于JSON对象和字符串转换的两个方法:

JSON.parse(): 用于将一个JSON字符串转换为JavaScript对象

JSON.parse('{"name":"Howker"}');JSON.parse('{name:"Stack"}') ;   // 错误JSON.parse('[18,undefined]') ;   // 错误

JSON.stringify():用于将JavaScript值转换为JSON字符串。

JSON.stringify({"name":"Tonny"})

AJAX

​ AJAX(Asynchronous Javascript And XML)翻译成中文就是“异步的Javascript和XML”。即使用Javascript语言与服务器进行异步交互,传输的数据为XML(当然,传输的数据不只是XML)。

​ AJAX 不是新的编程语言,而是一种使用现有标准的新方法。

​ AJAX 最大的优点是在不重新加载整个页面的情况下,可以与服务器交换数据并更新部分网页内容。(这一特点给用户的感受是在不知不觉中完成请求和响应过程)

​ AJAX 不需要任何浏览器插件,但需要用户允许JavaScript在浏览器上执行。

同步异步概念:

  • 同步提交:客户端发出一个请求后,需要等待服务器响应结束后,才能发出第二个请求;
  • 异步提交:客户端发出一个请求后,无需等待服务器响应结束,就可以发出第二个请求。

特点:

  1. 异步提交
  2. 局部刷新
前端发送请求到后端的方法 请求方法
浏览器窗口手动输入网址 get请求
a标签的href属性 get(默认)/post请求
form表单 get(默认)/post请求
ajax get/post请求

ajax基本语法

​ 提交的地址

​ 提交的方式

​ 提交的数据

​ 回调函数

示例:

    
Title
+ =
# views.pydef ajax_test(request):    if request.method=='POST':        i1=request.POST.get('i1')        i2=request.POST.get('i2')        ret=int(i1)+int(i2)        return HttpResponse(ret)    return render(request,'ajax_test.html')
# url.pyfrom django.conf.urls import urlfrom app01 import viewsurlpatterns=[    url(r'^ajax_test/',views.ajax_test),]

AJAX常见应用场景:

搜索引擎根据用户输入的关键字,自动提示检索关键字。

还有一个很重要的应用场景就是注册时候的用户名的查重。

其实这里就使用了AJAX技术!当文件框发生了输入变化时,使用AJAX技术向服务器发送一个请求,然后服务器会把查询到的结果响应给浏览器,最后再把后端返回的结果展示出来。

  • 整个过程中页面没有刷新,只是刷新页面中的局部位置而已!
  • 当请求发出后,浏览器还可以进行其他操作,无需等待服务器的响应!

5d034f19172c433021.png

//ajax默认传输数据的编码格式也是urlencoded$('#d1').click({    $.ajax({    //提交的地址    url:'/index',  // url可以不写,默认就是往当前页面打开的地址提交请求    //提交方式    type:'post',    //提交的数据    data:{'name':'qzk','password':'123'},  //数据一般会在前端页面中铜鼓选择器去筛选出来    //回调函数    success:functino(data){    alert(data)}})})
$('#d1').click({    $.ajax({    //提交的地址    url:'',  // url可以不写,默认就是往当前页面打开的地址提交请求    //提交方式    type:'post',    //提交的数据    data:{    'i1':$('#i1').val(),    'i2':$('#i2').val()},  //数据一般会在前端页面中铜鼓选择器去筛选出来    //回调函数    success:functino(data){    $('#i3').val(data)}})})
def index(request):    if request.method=='POST':        i1=request.POST.get("i1")        i2=request.POST.get("i2")        res=int(i1)+int(i2)        return...

AJAX的优缺点:

优点:

  • AJAX使用JavaScript 技术想服务器发送异步请求;
  • AJAX请求无需刷新整个页面
  • 因为服务器响应内容不再是整个页面,,而是页面中的部分内容,所以AJAX性能高;
  • 两个关键点:1.局部刷新,2.异步请求

最基本的jQuery发送ajax请求示例:

    
Title

用户名已存在

{#下面这一项是基于jQuery的基础上自动给我们的每一个ajax绑定一个请求头信息,类似于form表单提交post数据必须要有的csrf_token一样#}{#否则我的Django中间件里面的校验csrf_token那一项会认为你这个请求不是合法的,阻止你的请求#}
# views.pydef index(request):    if request.method=='POST':        ret={'flag':False}        username=request.POST.get('username')        if username=='JBY':            ret['flag']=True            import json            return HttpResponse(json.dumps(ret))    return render(request,'index.html')

示例二:发送文件格式数据(需要借助于内置对象 Formdata)

    
Title

AJAX发送json格式的数据(contentType:'application/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)           }       });

JS实现AJAX(了解)

var b2 = document.getElementById("b2");  b2.onclick = function () {    // 原生JS    var xmlHttp = new XMLHttpRequest();    xmlHttp.open("POST", "/ajax_test/", true);    xmlHttp.setRequestHeader("Content-type", "application/x-www-form-urlencoded");    xmlHttp.send("username=q1mi&password=123456");    xmlHttp.onreadystatechange = function () {      if (xmlHttp.readyState === 4 && xmlHttp.status === 200) {        alert(xmlHttp.responseText);      }    };  };

AJAX请求如何设置csrf

​ 不论是ajax还是谁,只要是向我Django提交post请求的数据,都必须校验csrf_token来防伪跨站请求,那么如何在我的ajax中弄这个csrf_token呢,我又不像form表单那样可以在表单内部通过一句{% csrf_token %}就搞定了......

方式一

​ 通过获取隐藏的input标签中的csrfmiddlewaretoken值,放置在data中发送。

$.ajax({  url: "/cookie_ajax/",  type: "POST",  data: {    "username": "Tonny",    "password": 123456,    "csrfmiddlewaretoken": $("[name = 'csrfmiddlewaretoken']").val()  // 使用JQuery取出csrfmiddlewaretoken的值,拼接到data中  },  success: function (data) {    console.log(data);  }})

方法二:

​ 通过获取返回的cookie中的字符串 放置在请求头中发送。

​ 注意:需要引入一个jquery.cookie.js插件。

$.ajax({  url: "/cookie_ajax/",  type: "POST",  headers: {"X-CSRFToken": $.cookie('csrftoken')},  // 从Cookie取csrf_token,并设置ajax请求头  data: {"username": "Q1mi", "password": 123456},  success: function (data) {    console.log(data);  }})

方式三:

​ 或者用自己写一个getCookie方法:

function getCookie(name) {    var cookieValue = null;    if (document.cookie && document.cookie !== '') {        var cookies = document.cookie.split(';');        for (var i = 0; i < cookies.length; i++) {            var cookie = jQuery.trim(cookies[i]);            // Does this cookie string begin with the name we want?            if (cookie.substring(0, name.length + 1) === (name + '=')) {                cookieValue = decodeURIComponent(cookie.substring(name.length + 1));                break;            }        }    }    return cookieValue;}var csrftoken = getCookie('csrftoken');

每一次都这么写太麻烦了,可以使用$.ajaxSetup()方法为ajax请求统一设置。

function csrfSafeMethod(method) {  // these HTTP methods do not require CSRF protection  return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));}$.ajaxSetup({  beforeSend: function (xhr, settings) {    if (!csrfSafeMethod(settings.type) && !this.crossDomain) {      xhr.setRequestHeader("X-CSRFToken", csrftoken);    }  }});

将下面的文件配置到你的Django项目的静态文件中,在html页面上通过导入该文件即可自动帮我们解决ajax提交post数据时校验csrf_token的问题,(导入该配置文件之前,需要先导入jQuery,因为这个配置文件内的内容是基于jQuery来实现的)

批量插入数据

"""自己推到的过程"""def booklist(request):    # 动态插入100条数据    for i in range(100):        models.Book2.objects.create(name='第%s本书'%i)    l = []    for i in range(10000):        l.append(models.Book2(name='第%s本书'%i))    models.Book2.objects.bulk_create(l)    # 查询所有的书籍展示到前端页面    """对批量数据进行分页显示(后期直接用模块的导入)"""    # 数据的总条数    all_count = models.Book2.objects.all().count()    # 要访问的当前页    current_page = request.GET.get('page', 1)  # 用户不传默认展示第一页    current_page = int(current_page)    # 每页展示多少条数据    per_page_num = 10    # 获取总页数    pager_nums,more = divmod(all_count,per_page_num)    if more:        pager_nums += 1    html = ''    for i in range(1,pager_nums+1):        html += '
  • %s
  • '%(i,i) # 起始位置 page_start = (current_page-1)*per_page_num # 终止位置 page_end = current_page*per_page_num book_list = models.Book2.objects.all()[page_start:page_end] return render(request,'booklist.html',locals())

    分页使用

    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('''                    
    ''') return ''.join(page_html_list)
    # views.pydef booklist(request):    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]    return render(request,'booklist.html',locals())# 然后前端再对传过去的数据进行渲染
        
    Title
    {% for book in page_queryset %}
    {% endfor %}
    id name
    { { book.pk }} { { book.name }}
    {
    { page_obj.page_html|safe }}

    转载于:https://www.cnblogs.com/qianzhengkai/p/11024356.html

    你可能感兴趣的文章
    深入理解 JavaScript 事件循环(一)— event loop
    查看>>
    Hive(7)-基本查询语句
    查看>>
    Redis快速入门
    查看>>
    注意java的对象引用
    查看>>
    C++ 面向对象 类成员函数this指针
    查看>>
    inline函数的总结
    查看>>
    【Jquery】$.Deferred 对象
    查看>>
    Python字符编码
    查看>>
    leetcode 49. 字母异位词分组(Group Anagrams)
    查看>>
    NSPredicate的使用,超级强大
    查看>>
    自动分割mp3等音频视频文件的脚本
    查看>>
    财务结算的目的和一般流程
    查看>>
    判断字符串是否为空的注意事项
    查看>>
    布兰诗歌
    查看>>
    老李分享:5个衡量软件质量的标准
    查看>>
    Xcode部分插件无法使用识别的问题
    查看>>
    set学习记录
    查看>>
    用函数写注册功能
    查看>>
    JVM笔记4:Java内存分配策略
    查看>>
    IE8 window.open 不支持此接口 的问题解决
    查看>>