摘要
-
MTV与MVC
-
多对多表三种创建方式
-
ajax ,前后端传输数据编码格式contentType
-
批量插入数据和自定义分页器
一、MVC与MTV
-
MVC(Model View Controller 模型-视图-控制器)
是一种Web架构的模式,所谓MVC就是把web应用分为模型(M),控制器(C),视图(V)三层;他们之间以一种插件似的,松耦合的方式连接在一起。模型负责业务对象与数据库的对象(ORM),视图负责与用户的交互(页面),控制器(C)接受用户的输入调用模型和视图完成用户的请求。
Model: 代表数据存取层,
View 代表的是系统中选择显示什么和怎么显示的部分,
Controller 指的是系统中根据用户输入并视需要访问模型,以决定使用哪个视图的那部分。 -
MTV(Model Templates View 模型-模板-视图)Django框架就是MTV模型:
Models:数据存取层。 该层处理与数据相关的所有事务: 如何存取、如何验证有效,是一个抽象层,用来构建和操作你的web应用中的数据,模型是你的数据的唯一的、权威的信息源。它包含你所储存数据的必要字段和行为。通常,每个模型对应数据库中唯一的一张表。
模板(templates):即表现层。 该层处理与表现相关的决定: 如何在页面或其他类型文档中进行显示。模板层提供了设计友好的语法来展示信息给用户。使用模板方法可以动态地生成HTML。模板包含所需HTML 输出的静态部分,以及一些特殊的语法,描述如何将动态内容插入。
视图(views):业务逻辑层,该层包含存取模型及调取恰当模板的相关逻辑。用于封装负责处理用户请求及返回响应的逻辑。视图可以看作是前端与数据库的中间人,他会将前端想要的数据从数据库中读出来给前端。他也会将用户要想保存的数据写到数据库。Django的MTV模式本质上与MVC模式没有什么差别,也是各组件之间为了保持松耦合关系,只是定义上有些许不同,Django的MTV分别代表:
Model(模型):负责业务对象与数据库的对象(ORM)
Template(模版):负责如何把页面展示给用户
View(视图):负责业务逻辑,并在适当的时候调用Model和Template
此外,Django还有一个url分发器,它的作用是将一个个URL的页面请求分发给不同的view处理,view再调用相应的Model和Template
二、多对多表的创建
- 第①种:Django自带的ORM自动创建的多对多表(ManyToManyField(to='...‘))
# 多表查询示例表 class Book(models.Model): title = models.CharField(max_length=32) price = models.DecimalField(max_digits=8, decimal_places=2) publish_date = models.DateField(auto_now_add=True) # 外键关系 # 一对多:(外键) publish = models.ForeignKey(to='Publish') # 多对多: author = models.ManyToManyField(to='Author') # 这是一个虚拟字段, 信号字段 class Author(models.Model): name = models.CharField(max_length=32) age = models.IntegerField()
很显然,Django自动创建的多对多表,支持双下划线查询语法。
- 第②种纯手动创建多对多表:
# 多对多表创建实例: class MyBook(models.Model): title = models.CharField(max_length=32) price = models.DecimalField(max_digits=8, decimal_places=2) publish_date = models.DateField(auto_now_add=True) class MyAuthor(models.Model): name = models.CharField(max_length=32) age = models.IntegerField() class MyBook2MyAuthor(models.Model): # 这里的book和author不要加_id,因为会Django识别ForenginKey,并给其自动加上_id book = models.ForeignKey(to='MyBook') author = models.ForeignKey(to='MyAuthor') #纯手动创建多对多,可以在该关联表中加入自己需要的字段 info = models.CharField(max_length=32)
# models中表关系映射创建完了,记得一定要对Django数据库进行迁移(保存)操作 数据库迁移方法一: cmd命令: python3 manage.py makemigrations migrate 数据库迁移方法二: pycharm中菜单栏Tools下有个Run manage.py Task...打开输入如下命令 makemigrations migrate
数据库迁移完之后我们看看创建的三张表(Navicat查看):
先创建一些数据:
提示一下:为了直接在Django页面中运行我们的测试表查询代码,快速显示结果,我们需要对Django进行配置一下:配置方法见我另一篇博客文中单表查询处:点我跳转# 测试表查询py文件内:
import os if __name__ == "__main__": os.environ.setdefault("DJANGO_SETTINGS_MODULE", "created_by_pycharm.settings") import django django.setup() from app01 import models models.MyAuthor.objects.create(name='吴承恩', age=100) models.MyAuthor.objects.create(name='吴彦祖', age=30) models.MyAuthor.objects.create(name='刘德华', age=45) models.MyAuthor.objects.create(name='刘志鹏', age=18) models.MyAuthor.objects.create(name='曹雪芹', age=120) res1 = models.MyBook.objects.create(title='西游记', price=66.6) res2 = models.MyBook.objects.create(title='东游记', price=99.9) res3 = models.MyBook.objects.create(title='南游记', price=88.8) res4 = models.MyBook.objects.create(title='北游记', price=68.6) # 由于多对多这张表是我们自己创建的,所以在数据库中是真实存在的,它关联着MyAutho和 # MyBook这2张表,所以添加表关系的时候在任何一个MyBook或者是MyAuthor # 表对象点mybook2myauthor_set.add()的方法是行不通的: # models.MyBook.objects.filter(pk=1).first().mybook2myauthor.add(5) # 错误提示:AttributeError: 'MyBook' object has no attribute 'mybook2myauthor' # 因为外键建立在多对多那张关联表中,所以要添加关系需要在这张表中动手脚 models.MyBook2MyAuthor.objects.create(book_id=1, author_id=1) models.MyBook2MyAuthor.objects.create(book_id=1, author_id=2) models.MyBook2MyAuthor.objects.create(book_id=2, author_id=2) models.MyBook2MyAuthor.objects.create(book_id=2, author_id=3) models.MyBook2MyAuthor.objects.create(book_id=3, author_id=4) models.MyBook2MyAuthor.objects.create(book_id=4, author_id=5)下面来验证手动创建的多对多表可否使用Django的ORM表查询和基于双下划线的反向查询:
# res1 = models.MyBook.objects.filter(pk=1).first().author.name # print(res1) # 报错:'MyBook' object has no attribute 'author' # res2 = models.MyBook.objects.filter(pk=1).first().mybook2myauthor_set.all().info # print(res2) # res4 = models.MyBook.objects.filter(pk=1).first().author_set.all().name # print(res4) # 报错 # res5 = models.MyBook.objects.filter(pk=1).values('author__name') # print(res5) # 报错 很显然用原来的orm方法貌似不行,同时用下划线试了也不行
很显然,外键的建立位置变了,肯定这样查不行,外键全部在mybook2myauthor这张表中,所以要想从一张表查到另外一张表,必须要先经过mybook2myauthor这张表。
至于如何查询,本文不作深入探讨,咱们继续下一种方法:半自动化建立多对多表。 - 半自动创建多对多表(该方法的可拓展性高,并且符合ORM查询规则,在项目中使用频率也最高,需要重点掌握)
class Books(models.Model): title = models.CharField(max_length=32) price = models.DecimalField(max_digits=8, decimal_places=2) publish_date = models.DateField(auto_now_add=True) author = models.ManyToManyField(to='Authors', through='Books2Authors', through_fields=('book', 'author')) class Authors(models.Model): name = models.CharField(max_length=32) age = models.IntegerField() class Books2Authors(models.Model): book = models.ForeignKey(to='Books') author = models.ForeignKey(to='Authors') #纯手动创建多对多,可以在该关联表中加入自己需要的字段 info = models.CharField(max_length=32)
# 创建一些数据,添加表关系 models.Authors.objects.create(name='吴承恩', age=100) models.Authors.objects.create(name='吴彦祖', age=30) models.Authors.objects.create(name='刘德华', age=45) models.Authors.objects.create(name='刘志鹏', age=18) models.Authors.objects.create(name='曹雪芹', age=120) res1 = models.Books.objects.create(title='西游记', price=66.6) res2 = models.Books.objects.create(title='东游记', price=99.9) res3 = models.Books.objects.create(title='南游记', price=88.8) res4 = models.Books.objects.create(title='北游记', price=68.6) models.Books2Authors.objects.create(book_id=1, author_id=1) models.Books2Authors.objects.create(book_id=1, author_id=2) models.Books2Authors.objects.create(book_id=2, author_id=2) models.Books2Authors.objects.create(book_id=2, author_id=3) models.Books2Authors.objects.create(book_id=3, author_id=4) models.Books2Authors.objects.create(book_id=4, author_id=5)
# ORM查询可行性
res = models.Books.objects.filter(pk=1).first().author.all().values('name') res1 = models.Authors.objects.filter(pk=1).first().books_set.all().values('title') print(res) # <QuerySet [{'name': '吴承恩'}, {'name': '吴彦祖'}]> print(res1) # <QuerySet [{'title': '西游记'}]># 双下划线查询可行性: res = models.Books.objects.filter(pk=1).values_list('author__name') res1 = models.Authors.objects.filter(pk=1).values_list('books__title') print(res) # <QuerySet [('吴承恩',), ('吴彦祖',)]> print(res1) # <QuerySet [('西游记',)]>
通过上面查询结果可知这种半自动创建多对多表的方法可以使用ORM查询方法也支持双下划线方法
三、ajax,前后端传输编码格式contentType
-
①urlencoded (默认格式)
对应数据格式:name=jason&password=666
后端获取方式:request.POST
django会将urlencoded编码数据解析自动放到request.POST中 -
②formdata(form表单传输文件编码格式)
注意form表单默认的传输编码格式是urlencoded(enctype="application/x-www-form-urlencoded"),如果需要传输文件,这里需要手动设置成formdata格式(enctype="multipart/form-data"),
后端:通过request.POST 继续获取普通字符串格式数据,通过request.FILES获取文件格式数据 -
③JSON格式(ajax支持)
什么是JSON:
- SON 指的是 JavaScript 对象表示法(JavaScript Object Notation)
- JSON 是轻量级的文本数据交换格式
- JSON 独立于语言 *
- JSON 具有自我描述性,更易理解
* JSON 使用 JavaScript 语法来描述数据对象,但是 JSON 仍然独立于语言和平台。JSON 解析器和 JSON 库支持许多不同的编程语言。
合格的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;} // 不能使用函数和日期对象 } -
关于JSON在JavaScript中的2个方法:
stringfy与parse方法
JavaScript中关于JSON对象和字符串转换的两个方法:
JSON.parse(): 用于将一个 JSON 字符串转换为 JavaScript 对象(json只认双引的字符串格式)JSON.parse('{"name":"Howker"}'); JSON.parse('{name:"Stack"}') ; // 错误 JSON.parse('[18,undefined]') ; // 错误
JSON.stringify(): 用于将 JavaScript 值转换为 JSON 字符串。
JSON.stringify({"name":"Tonny"}) -
补充
JSON与XML的区别
JSON 格式于2001年由 Douglas Crockford 提出,目的就是取代繁琐笨重的 XML 格式。
JSON 格式有两个显著的优点:书写简单,一目了然;符合 JavaScript 原生语法,可以由解释引擎直接处理,不用另外添加解析代码。所以,JSON迅速被接受,已经成为各大网站交换数据的标准格式,并被写入ECMAScript 5,成为标准的一部分。
XML和JSON都使用结构化方法来标记数据,下面来做一个简单的比较。
用XML表示中国部分省市数据如下:
XML格式<?xml version="1.0" encoding="utf-8"?> <country> <name>中国</name> <province> <name>黑龙江</name> <cities> <city>哈尔滨</city> <city>大庆</city> </cities> </province> <province> <name>广东</name> <cities> <city>广州</city> <city>深圳</city> <city>珠海</city> </cities> </province> <province> <name>台湾</name> <cities> <city>台北</city> <city>高雄</city> </cities> </province> <province> <name>新疆</name> <cities> <city>乌鲁木齐</city> </cities> </province> </country>