详情请点阅读全文
一、插入、更新和删除
调用一个模型类对象的save方法的时候就可以实现对模型类对应数据表的插入和更新。
调用一个模型类对象的delete方法的时候就可以实现对模型类对应数据表数据的删除。
二、自关联
自关联是一种特殊的一对多的关系。 【案例】:显示广州市的上级地区和下级地区。
地区表:id, atitle, aParent_id;
mysql终端中批量执行sql语句:source areas.sql;
第1步,添加地区模型类 app1/models.py 【关系属性】,代表当前地区的父级地区
1 2 3 4 5 6 7 8 9 class AreaInfo (models.Model) : '''地区模型类''' atitle = models.CharField(max_length=20 ) aParent = models.ForeignKey('self' , null=True , blank=True )
第2步,创建迁移,应用迁移创建对应表 1 2 3 4 5 6 7 8 9 10 11 D:\a\django-app\project1>py manage.py makemigrations Migrations for 'app1': app1\migrations\0004_auto_20200107_1148.py - Alter field btitle on bookinfo - Create model AreaInfo D:\a\django-app\project1>py manage.py migrate Operations to perform: Apply all migrations: admin, app1, auth, contenttypes, sessions Running migrations: Applying app1.0004_auto_20200107_1148... OK
查看表mysql命令窗:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 mysql> show databases; +--------------------+ | Database | +--------------------+ | information_schema | | mysql | | performance_schema | | sakila | | spiders | | sys | | test888 | | world | +--------------------+ 8 rows in set (0.07 sec) mysql> use test888 Database changed mysql> show tables; +----------------------------+ | Tables_in_test888 | +----------------------------+ | app1_areainfo | | app1_bookinfo | | app1_heroinfo | | auth_group | | auth_group_permissions | | auth_permission | | auth_user | | auth_user_groups | | auth_user_user_permissions | | django_admin_log | | django_content_type | | django_migrations | | django_session | +----------------------------+ 13 rows in set (0.00 sec) mysql> desc app1_areainfo; +------------+-------------+------+-----+---------+----------------+ | Field | Type | Null | Key | Default | Extra | +------------+-------------+------+-----+---------+----------------+ | id | int(11) | NO | PRI | NULL | auto_increment | | atitle | varchar(20) | NO | | NULL | | | aParent_id | int(11) | YES | MUL | NULL | | +------------+-------------+------+-----+---------+----------------+ 3 rows in set (0.11 sec)
第3步,把地区数据表导入刚建的表
表位置:q网盘\源码【area.sql】
把例如:INSERT INTO app1_areainfo VALUES ('110000', '北京市', NULL);
中的【app1_】改成 【对应的表名_】
进入sql命令窗:即可导入(路径不要有中文空格等) 1 2 3 4 use test888; #使用对应的表 source E:/pro_sql/test.sql; #导入数据 # 执行效果: Query OK, 1 row affected (0.12 sec)
查询刚导入的表效果 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 select * from app1_areainfo; | 659000 | 省直辖行政单位 | 650000 | | 659001 | 石河子市 | 659000 | | 659002 | 阿拉尔市 | 659000 | | 659003 | 图木舒克市 | 659000 | | 659004 | 五家渠市 | 659000 | | 990000 | 新疆建设兵团 | NULL | | 990100 | 第一师 | 990000 | | 990200 | 第二师 | 990000 | | 990300 | 第三师 | 990000 | | 990400 | 第四师 | 990000 | | 990500 | 第五师 | 990000 | | 990600 | 第六师 | 990000 | | 990700 | 第七师 | 990000 | | 990800 | 第八师 | 990000 | | 990900 | 第九师 | 990000 | | 991000 | 第十师 | 990000 | | 991100 | 建工师 | 990000 | | 991200 | 第十二师 | 990000 | | 991300 | 第十三师 | 990000 | | 991400 | 第十四师 | 990000 | +--------+-----------------------------------------------+------------+
第4步,app1/views.py 编辑对应函数,读取地区信息 1 2 3 4 5 6 7 8 9 10 11 12 from booktest.models import BookInfo,AreaInfodef areas (request) : '''获取广州市的上级地区和下级地区''' area = AreaInfo.objects.get(atitle='广州市' ) parent = area.aParent children = area.areainfo_set.all() return render(request, 'app1/areas.html' , {'area' :area,'parent' :parent, 'children' :children})
第5步,配置app1/urls.py 展示对应省市区信息
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 from django.urls import path,re_pathfrom . import viewsurlpatterns=[ path('app1/' ,views.index), path('books/' ,views.books), re_path(r"^detail/(\d+)" ,views.detail), path('addInfo/' ,views.addInfo), path(r'delete/<int:bid>' ,views.deleteInfo), path(r'area/' ,views.areas), ]
第6步,添加展示模板templates/app1/areas.html 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 <!DOCTYPE html> <html lang="zh" > <head> <meta charset="UTF-8" > <title>自关联案例</title> </head> <body> <h1>当前地区</h1> {{ area.atitle }}<br/> <h1>父级地区</h1> {{ parent.atitle }}<br/> <h1>下级地址</h1> <ul> {% for child in children %} <li>{{ child.atitle }}</li> {% endfor %} </ul> </body> </html>
效果: 当前地区: 广州市
父级地区: 广东省
下级地址: 荔湾区 越秀区 海珠区 天河区 白云区 黄埔区 番禺区 花都区 南沙区 萝岗区 增城市 从化市
三、管理器(Manager) 问:BookInfo.objects.all()->objects是一个什么东西呢?
答:objects是Django帮我自动生成的管理器对象,通过这个管理器可以实现对数据的查询。
objects是models.Manger类的一个对象。自定义管理器之后Django不再帮我们生成默认的objects管理器。
1 2 3 4 py manage.py shell >>> from app1.models import BookInfo,HeroInfo>>> type(BookInfo.objects)<class 'django .db .models .manager .Manager '>
1 自定义模型管理器类 1)自定义一个管理器类,这个类继承models.Manger类。 2)再在具体的模型类里定义一个自定义管理器类的对象。
例1:在app1/models.py下定义一个管理器类 自定一个Manager类对象,管理器对象 book = models.Manager()
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 class BookInfo (models.Model) : '''图书模型类''' btitle = models.CharField(max_length=20 , db_column='title' ) bpub_date = models.DateField() bread = models.IntegerField(default=0 ) bcomment = models.IntegerField(default=0 ) isDelete = models.BooleanField(default=False ) book = models.Manager()
自定义管理器类之后再查询数据就变成如下 由:BookInfo.objects.all()
变:BookInfo.book.all()
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 >>> quit()D:\a\django-app\project1>py manage.py shell Python 3.7 .1 (v3.7 .1 :260 ec2c36a, Oct 20 2018 , 14 :57 :15 ) [MSC v.1915 64 bit (AMD6 4 )] on win32Type "help" , "copyright" , "credits" or "license" for more information. (InteractiveConsole) >>> from app1.models import BookInfo>>> BookInfo.book.all() <QuerySet [<BookInfo: 天龙八部>, <BookInfo: 三国演义>, <BookInfo: 红楼梦>, <Book Info: 水浒传>]> >>> BookInfo.objects.all() Traceback (most recent call last): File "<console>" , line 1 , in <module> AttributeError: type object 'BookInfo' has no attribute 'objects'
2 自定义管理器类的应用场景 1)改变查询的结果集。
比如调用BookInfo.books.all()返回的是没有删除的图书的数据。例2:自定义Manager类 【1】自定义一个BookInfoManager类,实现查寻数据只返回isDelete=False(删除标记(伪删除))的书 【2】使用自定义的manager类1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 from django.db import modelsclass BookInfoManager (models.Manager) : '''图书模型管理器类''' def all (self) : books = super().all() books = books.filter(isDelete=False ) return books class BookInfo (models.Model) : '''图书模型类''' btitle = models.CharField(max_length=20 ,unique=True ) bpub_date = models.DateField() bread = models.IntegerField(default=0 ) bcomment = models.IntegerField(default=0 ) isDelete = models.BooleanField(default=False ) objects = BookInfoManager()
2)添加额外的方法。
管理器类中定义一个方法帮我们操作模型类对应的数据表。
使用self.model()就可以创建一个跟自定义管理器对应的模型类对象。
例3,把插入图书各个语句封装成一个BookInfo类的函数: app1/models.py 1.【封装插入图书方法为BookInfo的函数】 2.使用时只需要 BookInfo.create_book(书标题,日期)
即可使用详情:
1 2 3 4 '''使用下一步封装的函数''' from app1.models import BookInfoBookInfo.create_book('test' ,'1991-1-1' ) book.btitle
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 '''定义类的封装插入图书函数''' from django.db import modelsclass BookInfo (models.Model) : '''图书模型类''' btitle = models.CharField(max_length=20 , db_column='title' ) bpub_date = models.DateField() bread = models.IntegerField(default=0 ) bcomment = models.IntegerField(default=0 ) isDelete = models.BooleanField(default=False ) @classmethod #【封装插入图书方法为BookInfo的函数】 def create_book (cls, btitle, bpub_date) : '''添加一本图书''' obj = cls() obj.btitle = btitle obj.bpub_date = bpub_date obj.save() return obj
例4,一般把增、删、改、查自定义函数写到Manger自定义类里 2.封装方法,操作模型类对应的数据表(增删改查)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 class BookInfoManager (models.Manager) : '''图书模型管理器类''' def all (self) : books = super().all() books = books.filter(isDelete=False ) return books def create_book (self, btitle, bpub_date) : '''添加一本图书''' model_class = self.model book = model_class() book.btitle = btitle book.bpub_date = bpub_date book.save() return book
调用: 1 2 3 4 5 from app1.models import BookInfoBookInfo.objects.create(btitle='test3' ,bpub_ date='1990-10-10' ) <BookInfo:BookInfo object>
上一步写的自定义函数先注释掉:
小结: 【模型管理器对象】
改变原有查询的结果集。
封装方法,用户操作管理器对象所在模型类对应的数据表。
3. 模型管理器类、模型类间关系
四、元选项(指定表名) Django默认生成的表名: 应用名小写_模型类名小写。
元选项: 需要在模型类中定义一个元类Meta,在里面定义一个类属性db_table就可以指定表名。
应用场景:应用名(app1)和表名不一致情形 【问题】比如对应用名不满意想换个别的名字,此时表名已经生成了,这时应该怎么办呢?
【解决】就可通过元选项解决。实战app1/models.py 【1】指定表的名字1 2 3 4 5 6 7 8 9 class AreaInfo (models.Model) : '''地区模型类''' atitle = models.CharField(max_length=20 ) aParent = models.ForeignKey('self' , null=True , blank=True ) class Meta : db_table = 'areas'