django 进阶-- 模型


1.使用mysql
 python2下安装mysql-python:
pip install mysql-python
python3下安装pymysql:
pip install pymysql
安装完之后,还需要在test2/__init__.py中加如下内容:
import pymysqlpymysql.install_as_MySQLdb()

使用mysql数据库,数据库需要自己创建,只需要创建数据库,不需要创建表,登录mysql数据库,创建数据库名称为test2, 注意要设置数据库的编码为utf8。
create database test2 charset=utf8;
数据库创建完后,需要在settings.py文件中的database一项设置如下:
//更改数据库设置后,原数据库的数据需要导入才能使用。否则没有数据。
DATABASES = {
  'default': {
    'ENGINE': 'django.db.backends.mysql', # 引擎为mysql
    'NAME': 'test2', # 设置数据库名称
    'USER': 'root', # 设置登录用户名
    'PASSWORD': 'mysql', # 设置登录密码
    'HOST': 'localhost', # 设置数据库主机位置
    'PORT': '3306', # 设置端口,默认是3306
    }
}
设置完之后,使用模型类迁移,会自动在mysql数据库中创建表。

2.定义模型类
模型类必须继承自Model类,位于包django.db.models中。提示:对于重要数据使用逻辑删除。

属性定义语法为:
属性=models.字段类型(选项)

属性命名规则:
不能是python的保留关键字
不允许使用连续的下划线,因为连续下划线在查询中会用到
定义属性时需要指定字段类型
主键一般不用自己定义,django会自动创建自增长主键列

3.字段类型
类型
说明
AutoField
自动增长的IntegerField,通常不用指定,Django会自动创建
BooleanField
布尔字段,值为True或False
NullBooleanField
支持Null、True、False三种值
CharField
字符串,参数max_length表示最大字符个数
TextField
大文本字段,一般超过4000个字符时使用
IntegerField
整数
DecimalField
十进制浮点数,参数max_digits表示总位数,参数decimal_places表示小数位数
FloatField
浮点数
DateField
日期,参数auto_now表示自动保存最新的修改日期,默认值False,参数auto_now_add表示自动保存创建时的日期,默认值False,两个参数不能同时设置
TimeField
时间,参数同DateField
DateTimeField
日期和时间,参数同DateField
FileField
上传文件字段
ImageField
继承于FileField,对上传的内容进行校验,确保是有效的图片
关系字段类型
类型
说明
ForeignKey
一对多,将字段定义在多的一端中
ManyToManyField
多对多,将字段定义在两端中
OneToOneField
一对一,将字段定义在任意一端中
字段类型选项
类型
说明
null
如果为True,表示允许为空,默认值是False
blank
如果为True,则该字段允许为空白,默认值是False
db_column
字段的名称,如果未指定,则使用属性的名称
db_index
若值为True, 则在表中会为此字段创建索引,默认值是False
default
默认值
primary_key
若为True,则该字段会成为主键,默认是False,一般作为AutoField的选项
unique
如果为True, 这个字段在表中必须有唯一值,默认值是False

4.例子:
from django.db import models
#定义图书模型类
BookInfoclass BookInfo(models.Model):
    btitle = models.CharField(max_length=20) #图书名称
    bpub_date = models.DateField()#发布日期
    bread = models.IntegerField(default=0) #阅读量,默认值表示在创建模型对象时,不指定这个属性值,这个值就为0
    bcommet = models.IntegerField(default=0)#评论量
    isDelete = models.BooleanField(default=False)#逻辑删除

    class Meta:#元信息类
    db_table='bookinfo'#指定本类在数据表中的表名称

5. 模型类属性objects
//Manage对象同一个模型类只存在一个,即自定义了Manage对象或子类对象,objects就被替换。
  • objects叫做管理器,是Manager类型的对象,定义在from django.db import models中
  • 用于模型对象和数据库交互
  • object类属性是默认自动生成的,但是可以自定义管理器对象
  • 自定义管理器对象后,Django不再生成默认管理器对象objects
自定义管理器类主要用于两种情况:
  • 1.改变查询的结果集
  • 2.添加额外的方法

修改管理器objects的方式:
1.自定义管理器:
// 在模型类中创建一个models.Manage对象,模型类的objects属性就被替换成新建的对象。
class BookInfo(models.Model): (模型类中)
# 这样实例化一个Manager对象后,objects 变成了 books
# 相当于把管理器改了名字,没多大意义
books = models.Manager()

2.自定义图书管理器类步骤:
1. class BookInfoManager(models.Manager):
    def total(self): # 自定义一个查询所有结果集的方法
      return super().all().filter(isDelete=False) # 给objects添加了 total方法,相当于all的结果再进行过滤出状态为未删除的数据

2. 在模型类BookInfo中定义管理器:
class BookInfo(models.Model): ...
# 使用和objects相同的名称来实例化,objects在和原理功能相同的基础上,多了一个total方法
    objects = BookInfoManager()

图书管理器类中定义修改对象的方法步骤:
1.在models中:
class BookInfoManager(models.Manager):
  def total(self):
        return super().all().filter(isDelete=False)
# 定义方法,给所有的书名加上书名号
  def shuminghao(self, obj):
    for i in obj:
    i.btitle = "《%s》" % i.btitle
    return obj
2.在views中:
def index(request):
// 调用objects对象的方法,传入查询好的books对象
books = BookInfo.objects.shuminghao(BookInfo.objects.all())
context = {'title': '图书列表', 'books': books}
return render(request, 'booktest/index.html', context)

查询集
查询集特性及过滤器
查询两大特性
  • 惰性执行:创建查询集不会访问数据库,直到调用数据时,才会访问数据库,调用数据的情况包括迭代、序列化等。
  • 缓存:查询集的结果被存下来之后,再次查询时会使用之前缓存的数据。

查询集限制
  • 如果查询返回多个结果,这个结果类似列表,可以使用下标的方式进行限制,等同于sql中的limit和offset子句,不支持负数索引。
  • 如果获取一个对象,直接使用[0],等同于[0:1].get(),但是如果没有数据,[0]引发IndexError异常,[0:1].get()引发DoesNotExist异常

过滤器
返回列表的过滤器如下:
  • all():返回所有数据
  • filter():返回满足条件的数据
  • exclude():返回满足条件之外的数据,相当于sql语句中where部分的not关键字
  • order_by():排序
返回单个查询结果的过滤器如下:
  • get():返回单个满足条件的对象,如果未找到会引发"模型类.DoesNotExist"异常,如果多条被返回,会引发"模型类.MultipleObjectsReturned"异常。
  • count():返回当前查询的总条数
  • aggregate():聚合
  • exists():判断查询集中是否有数据,如果有则返回True,没有则返回False

条件查询
条件查询相当于sql语句中的where的功能,条件在filter()、exclude()、get()方法中定义,定义的语法是,属性名称+两个下划线+比较运算符,所以属性名不能包括多个下划线,具体写法如下:
属性名称__比较运算符=值

模糊查询
contain:查询包含某字符的记录,例:查询书名包含'传'的图书
BookInfo.objects.filter(btitle__contains='传')
startswith、endswith:查询以某字符开头的记录、查询以某字符结尾的记录,例:查询书名以'部'结尾的图书
BookInfo.objects.filter(btitle__endswith='部')
查询是否为空 isnull
查询某字段是否为空的记录,例:查询书名不为空的图书
BookInfo.objects.filter(btitle__isnull=False)
范围查询 in
查询某个范围内的记录,例:查询编号为1或3或5的图书
BookInfo.objects.filter(id__in = [1,3,5])
比较查询
gt、gte、lt、lte:大于、大于等于、小于、小于等于 例:查询编号大于3的图书
BookInfo.objects.filter(id__gt = 3)
日期查询
year、month、day、week_day、hour、minute、second:对日期时间类型的属性进行运算 例:查询1980年发表的图书
BookInfo.objects.filter(bpub_date__year=1980)
查询取反
返回不满足条件的记录,例:查询id不为3的图书信息
BookInfo.objects.exclude(id=3)
判等 exact
判断是否相等,例:查询编号为1的图书
list=BookInfo.objects.filter(id__exact=1)list=BookInfo.objects.filter(id=1) 和上面效果相同的简写方式

F对象
用于表字段之间的比较,使用前需要先导入这个模块
from django.db.models import F
例:查询阅读量大于等于评论量的图书
BookInfo.objects.filter(bread__gte=F('bcommet'))

Q对象
用于查询时的逻辑条件。not and or,可以对Q对象进行& | ~操作,使用前需要先导入这个模块
from django.db.models import Q
例:查询id大于3且阅读量大于30的图书的信息
BookInfo.objects.filter(id__gt=3, bread__gt=30)BookInfo.objects.filter(Q(id__gt=3)&Q(bread__gt=30)) 等价于上面
例:查询id大于3或者阅读量大于30的图书的信息
BookInfo.objects.filter(Q(id__gt=3)|Q(bread__gt=30))
例:查询id不等于3图书的信息
BookInfo.objects.filter(~Q(id=3))

查询结果排序 order_by
例:查询所有图书的信息,按照id从小到大进行排序
BookInfo.objects.all().order_by('id')BookInfo.objects.order_by('id')
例:查询所有图书的信息,按照id从大到小进行排序
BookInfo.objects.all().order_by('-id')
例:把id大于3的图书信息按阅读量从大到小排序显示
BookInfo.objects.filter(id__gt=3).order_by('-bread')

聚合查询aggregate // 对查询结果进行运算
对查询结果进行聚合操作,聚合函数包括:Avg,Count,Max,Min,Sum,被定义在django.db.models中,使用前要先导入:
from django.db.models import Sum,Count,Max,Min,Avg
例:查询所有图书的数目
BookInfo.objects.aggregate(Count('id'))BookInfo.objects.count() 上面写法等同于下面count()函数的写法
例:查询所有图书阅读量的总和
BookInfo.objects.aggregate(Sum('bread'))

连表查询
实现类似sql语句中的join查询语法,语法如下:
关联模型类名小写__属性名__运算符=值
例:查询图书,要求图书中英雄的描述包含‘八’
BookInfo.objects.filter(heroinfo__hcontent__contains='八')

自关联
对于地区信息、分类信息等数据,表结构非常类似,每个表的数据量十分有限,为了充分利用数据表的大量数据存储功能,可以可以设计成一张表,内部的关系字段指向本表的主键,这就是自关联的表结定义省市区表对应的模型类:
// ForeignKey 参数‘self’表示自关联
class AreaInfo(models.Model): atitle=models.CharField(max_length=30) # 名称 aParent=models.ForeignKey('self',null=True,blank=True) # 关系 构。 

class Meta:
db_table = 'df_goods_type' # 数据表中的表名
verbose_name = '商品种类' # 后台管理页面显示的类名称
verbose_name_plural = verbose_name # 后台管理页面显示的类名称的复数。如果不设置,自动在最后加s
abstract = True # 定义为抽象模型类,不会产生表,适用于公共属性

choices
# 字段属性中的一个,控制字段值的范围
status_choices = (
(0, '下架'), # 前面的是值,后面的是后台下拉显示名称
(1, '上架'),)

status = models.SmallIntegerField(default=1, choices=status_choices, verbose_name='商品状态')

你可能感兴趣的:(django)