上一篇把简单的模型与数据库的搭建写了一遍,但模型中有很多深入好用的写法补充一下。
同样的栗子,建立新的模型与数据库来写一写
1、依然是搭建环境
>>>django-admin startproject django2
>>>cd django2
配置数据库、语言、地区
django2/settings.py
DATABASES = { 'default': { 'ENGINE': 'django.db.backends.mysql', 'NAME': 'django2', 'USER': 'root', 'PASSWORD': '123456', 'HOST': 'localhost', 'PORT': '3306' } } LANGUAGE_CODE = 'zh-hans' TIME_ZONE = 'Asia/Shanghai'
# 创建应用 >>>python manage.py startapp booktest
把该应用添加到settings中
django2/settings.py
INSTALLED_APPS = ( 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', 'booktest' )
2、定义模型
booktest/models.py
class BookInfo(models.Model): btitle = models.CharField(max_length = 20) bpub_date = models.DateTimeField(db_column = 'pub_date') # db_column指定在数据库中呈现的字段名称 bread = models.IntegerField(default = 0) # default指定默认值 bcomment = models.IntegerField(null = False) # null指示该字段是否为空 True可以为空 False不能为空 isDelete = models.BooleanField(default = False) class Meta: db_table = 'bookinfo' # 指定数据库中生成的表明(默认是 应用名_模型类名 booktest_bookinfo) def __str__(self): return self.btitleclass HeroInfo(models.Model): hname = models.CharField(max_length = 10) hgender = models.BooleanField(default = True) # True:男 False:女 hcontent = models.CharField(max_length = 1000) isDelete = models.BooleanField(default = False) book = models.ForeignKey(BookInfo, on_delete = models.CASCADE) def __str__(self): return self.hname
创建数据库Django2后
# 制作迁移 >>>python manage.py makemigrations # 生成迁移 >>>python manage.py migrate
自定义管理器场景一:修改默认查询集
booktest/models.py
class BookInfo(models.Model): btitle = models.CharField(max_length = 20) bpub_date = models.DateTimeField(db_column = 'pub_date') # db_column指定在数据库中呈现的字段名称 bread = models.IntegerField(default = 0) # default指定默认值 bcomment = models.IntegerField(null = False) # null指示该字段是否为空 True可以为空 False不能为空 isDelete = models.BooleanField(default = False) class Meta: db_table = 'bookinfo' # 指定数据库中生成的表明(默认是 应用名_模型类名 booktest_bookinfo) def __str__(self): return self.btitle book1 = models.Manager() # 指定book1为模型类的管理器对象 book2 = BookInfoManager() # 用来下面写筛选 class HeroInfo(models.Model): hname = models.CharField(max_length = 10) hgender = models.BooleanField(default = True) # True:男 False:女 hcontent = models.CharField(max_length = 1000) isDelete = models.BooleanField(default = False) book = models.ForeignKey(BookInfo, on_delete = models.CASCADE) def __str__(self): return self.hname
在manage.py shell中,通过命令
>>>from booktest.models import BookInfo, HeroInfo # 导入模块 >>> BookInfo.book1.all() # 查看所有的书的信息 # 注意:这样写了以后,默认的管理器objects就不存在了
自定义管理器的场景二:添加创建的方法。
# 之前的写法 b = BookInfo() b.btitle = '射雕英雄传' b.bpub_date = datetime(year = 2018, month = 8, day = 11) b.save()
现在提供一个create()方法,只需要传入参数,即可创建对象
这个create()方法可以写在BookInfo中,也可以写在BookInfoManager中。官方推荐写在BookInfoManager中。
class BookInfoManager(models.Manager): def get_queryset(self): return super(BookInfoManager,self).get_queryset().filter(isDelete = False) def create(self, btitle, bpub_date): b = BookInfo() b.btitle = btitle b.bpub_date = bpub_date b.bread = 0 b.bcomment = 0 b.isDelete = False return b
# 注意python manage.py shell需要退出并重新进入。 # 测试代码: from booktest.models import * from datetime import datetime b = BookInfo.book2.create('程序员的自我修炼',datetime(2018,9,12)) b.save()
运行后,留意数据库的bookinfo表多了程序员的自我修炼一行
3、模型查询
''' 返回查询集合的方法,称为过滤器 all():获取所有的数据 filter():获取满足条件的数据 exclude():获取不满足条件的是数据 ''' # 注意:如果使用and与操作同时过滤两个条件,可以使用如下两种方法之一 >>>BookInfo.book1.filter(bread__gt=22, bcomment__lt=50) >>>BookInfo.book1.filter(bread__gt=22).filter(bcomment__lt=50) # order_by():排序 >>>BookInfo.book1.all().order_by("bread") # values():把一个对象构建成一个字典。最后返回一个列表 >>>BookInfo.book1.values() ''' 返回单个值的方法: get():返回单个满足条件的对象 如果返回多个数,会抛出MultipleObjectsReturned异常 如果未找到,会抛出DoesNotExist异常 ''' >>>BookInfo.book1.get(btitle='雪山飞狐') #count():返回当前查询的总条数(返回一个整数) >>>BookInfo.book1.all().count() # first():返回第一个对象 # last():返回最后一个对象 >>>BookInfo.book1.all().first() >>>BookInfo.book1.all().last() # exists():判断查询集中是否有数据,如果有返回True >>>BookInfo.book1.filter(bread__gt=20).exists() ''' 方法filter()、exclude()、get()……可以添加子查询运算符 比较运算符。格式为: 属性名_ _比较运算符 = 值 ''' # exact:表示判断相等。如果没有写比较运算符,默认则是exact。 # 所以下面两句是等效的 >>>BookInfo.book1.filter(bread__exact=20) >>>BookInfo.book1.filter(bread=20) # contains:是否包含 >>>BookInfo.book1.filter(btitle__contains='传') #startswith:以某个子串开头 # endswith:以某个子串结尾 >>>BookInfo.book1.filter(btitle__startswith='传') >>>BookInfo.book1.filter(btitle__endswith='传') # isnull:为空 #i snotnull:不为空 >>>BookInfo.book1.filter(btitle__isnull=False) # 注意:前面的操作都是区分大小写的。如果不区分大小写,可以在前面加上i。比如iexact、icontains、istartswith、iendswith等 # in:是否包含在范围内 >>>BookInfo.book1.filter(pk__in=[1,2,3]) >>>BookInfo.book1.filter(id__in=[1,2,3]) ''' gt:大于(Greater Than) gte:大于等于(Greater Than or Equal) lt:小于(Little Than) lte:小于等于(Little Than or Equal) ''' >>>BookInfo.book1.filter(bread__gte=20) # 注意:这些操作也可以对日期进行判断。包括year month day week_day hour minute second >>>from datetime import date >>>BookInfo.book1.filter(bpub_date__gt=date(1985,12,31)) # 跨表查询 # 语法:模型类名_ _属性名_ _比较 >>>BookInfo.book1.filter(heroinfo__hcontent__contains='八')