Django学习--模型组件详解

配置

在settings.py中保存了数据库的连接配置信息,Django默认初始配置使用sqlite数据库。

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
    }
}
  1. 使用MySQL数据库首先需要安装驱动程
pip install PyMySQL
  1. 在Django的工程同名子目录的init.py文件中添加如下语句
import pymysql

pymysql.install_as_MySQLdb()

作用是让Django的ORM能以mysqldb的方式来调用PyMySQL。

3.修改DATABASES配置信息

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'HOST': '127.0.0.1',  # 数据库主机
        'PORT': 3306,  # 数据库端口
        'USER': 'root',  # 数据库用户名
        'PASSWORD': 'mysql',  # 数据库用户密码
        'NAME': 'book'  # 数据库名字
    }
}
  1. 在MySQL中创建数据库
create database book charset=utf8;

定义模型类

1.定义模型类中的字段分成三部分
* 字段名
* 字段名不能使用python关键字或者mysql关键字
* 字段名不能出现连续的 下划线

  • 字段类型

    • 基本和数据库中的类型一致
    • 常见的字段类型:

      类型说明
      AutoField自动增长的IntegerField,通常不用指定,不指定时Django会自动创建属性名为id的自动增长属性
      BooleanField布尔字段,值为True或False
      AutoField支持Null、True、False三种值
      CharField字符串,参数max_length表示最大字符个数
      IntegerField整数
      FloatField浮点数
      DateField日期
  • 字段选项

    • 常见字段选项

      选项说明
      如果为True,表示允许为空,默认值是False
      blank如果为True,则该字段允许为空白,默认值是False
      db_column字段的名称,如果未指定,则使用属性的名称
      db_index若值为True, 则在表中会为此字段创建索引,默认值是False
      default默认
      primary_key若为True,则该字段会成为模型的主键字段,默认值是False,一般作为AutoField的选项使用
      unique如果为True, 这个字段在表中必须有唯一值,默认值是False
    • 外键级联操作

      • on_delete 级联操作有常见有三种可选
        • 同步删除
        • 拒绝删除
        • set null

示例代码:

from django.db import models


# Create your models here.

# Create your models here.
# 准备书籍列表信息的模型类
class BookInfo(models.Model):
    # 创建字段,字段类型...
    name = models.CharField(max_length=20, verbose_name='名称')
    pub_date = models.DateField(verbose_name='发布日期',null=True)
    readcount = models.IntegerField(default=0, verbose_name='阅读量')
    commentcount = models.IntegerField(default=0, verbose_name='评论量')
    is_delete = models.BooleanField(default=False, verbose_name='逻辑删除')

    class Meta:
        db_table = 'bookinfo'  # 指明数据库表名
        verbose_name = '图书'  # 在admin站点中显示的名称

    def __str__(self):
        """定义每个数据对象的显示信息"""
        return self.name

# 准备人物列表信息的模型类
class PersonInfo(models.Model):
    GENDER_CHOICES = (
        (0, 'male'),
        (1, 'female')
    )
    name = models.CharField(max_length=20, verbose_name='名称')
    gender = models.SmallIntegerField(choices=GENDER_CHOICES, default=0, verbose_name='性别')
    description = models.CharField(max_length=200, null=True, verbose_name='描述信息')
    # 外键
    # on_delete  级联操作       同步删除,拒绝删除,set null
    # models.CASCADE        CASCADE同步操作
    book = models.ForeignKey(BookInfo, on_delete=models.CASCADE, verbose_name='图书')  # 外键
    is_delete = models.BooleanField(default=False, verbose_name='逻辑删除')

    class Meta:
        db_table = 'peopleinfo'
        verbose_name = '人物信息'

    def __str__(self):
        return self.name

数据库操作

增加数据

方式1: save()

这种方式 数据不会自动入库

>>> book = BookInfo()
>>> book.name = '老陈回忆录'
>>> book.pub_date = '2018-11-11'
>>> 

1.png

想让数据入库 需要手动调用 save() 方法

>>> book.save()

2.png

方式1: create()

这种方式数据直接入库

>>> BookInfo.objects.create(name='那年老陈19岁',pub_date='2018-11-12')

<BookInfo: 那年老陈19岁>

3.png


修改

方式1: save()

修改模型的属性,手动调用 save方法 数据才会修改

>>> book =  BookInfo.objects.get(id=7)
>>> book.pub_date = '2016-11-11'
<!--需要手动执行save() 数据才会修改-->
>>> book.save()

44.png

方式2: update()

模型类执行update方法,数据直接修改,会返回受影响的行数

>>> BookInfo.objects.filter(id=8).update(readcount=100)
1
>>> 

55.png


删除

方式1: 通过模型类删除
>>> book = BookInfo.objects.get(pk=8)
>>> book
<BookInfo: 那年老陈19岁>
>>> book.delete()
(1, {'book.BookInfo': 1, 'book.PersonInfo': 0})
>>> 

77.png

方式2: 直接删

模型类.objects.get().delete()

>>> book = BookInfo.objects.get(id=7).delete()
>>> book
(1, {'book.BookInfo': 1, 'book.PersonInfo': 0})
>>> 

66.png



==查询==

基本查询

  • get 是获取一条记录
>>> BookInfo.objects.get(id=1)
<BookInfo: 射雕英雄传>
  • get 获取不到是会报异常 ==DoesNotExist==
>>> BookInfo.objects.get(id=11111)

book.models.DoesNotExist: BookInfo matching query does not exist.
  • all 获取所有数据
>>> BookInfo.objects.all()
<QuerySet [<BookInfo: 射雕英雄传>, <BookInfo: 天龙八部>, <BookInfo: 笑傲江湖>, <BookInfo: 雪山飞狐>]>
  • count 获取查询结果的个数
>>> BookInfo.objects.all().count()
4
>>> 

过滤查询

  • get过滤单一结果
  • filter过滤出多个结果
  • exclude排除掉符合条件剩下的结果

    1. get
  • 通过字段过滤一条结果

>>> BookInfo.objects.get(id=1)
<BookInfo: 射雕英雄传>
  • 使用属性名称__比较运算符=值 方式获取
>>> BookInfo.objects.get(id__exact=1)
<BookInfo: 射雕英雄传>
  • 通过主键的方式获取
>>> BookInfo.objects.get(pk=1)
<BookInfo: 射雕英雄传>
  • 使用filter过滤出结果集
>>> BookInfo.objects.filter(id=1)
<QuerySet [<BookInfo: 射雕英雄传>]>
>>> 

filter 和 get 区别 ,filter得到的是一个查询结果集,get得到的是一个对象

  1. filter 过滤出多个结果 (0,1,多个 都包括 多个结果中)

    • contains 包含
>>> BookInfo.objects.filter(name__contains='八')
<QuerySet [<BookInfo: 天龙八部>]>
  • startswith、endswith:以指定值开头或结尾。
>>> BookInfo.objects.filter(name__endswith='湖')
<QuerySet [<BookInfo: 笑傲江湖>]>
  • isnull:是否为null。
>>> BookInfo.objects.filter(name__isnull=False)
<QuerySet [<BookInfo: 射雕英雄传>, <BookInfo: 天龙八部>, <BookInfo: 笑傲江湖>, <BookInfo: 雪山飞狐>]>
  • in:是否包含在范围内。
>>> BookInfo.objects.filter(id__in=[1,2,3])
<QuerySet [<BookInfo: 射雕英雄传>, <BookInfo: 天龙八部>, <BookInfo: 笑傲江湖>]>
  • 比较查询
    • gt 大于
    • gte 大于等于
    • lt 小于
    • lte 小于等于
>>> BookInfo.objects.filter(id__gt=2)
<QuerySet [<BookInfo: 笑傲江湖>, <BookInfo: 雪山飞狐>]>
>>> BookInfo.objects.filter(id__gte=2)
<QuerySet [<BookInfo: 天龙八部>, <BookInfo: 笑傲江湖>, <BookInfo: 雪山飞狐>]>
>>> 
  • 不等于 exclude排除掉符合条件剩下的结果 相当于 not
>>> BookInfo.objects.exclude(id=2)
<QuerySet [<BookInfo: 射雕英雄传>, <BookInfo: 笑傲江湖>, <BookInfo: 雪山飞狐>]>
>>> 
  • 日期查询

year、month、day、week_day、hour、minute、second:对日期时间类型的属性进行运算。

>>> BookInfo.objects.filter(pub_date__year=1980)
<QuerySet [<BookInfo: 射雕英雄传>]>
>>> BookInfo.objects.filter(pub_date__gt='1990-1-1')
<QuerySet [<BookInfo: 笑傲江湖>]>
>>> 

F 和 Q 对象

F对象

对同一个对象中的两个不用的属性之间做比较使用F对象

>>> BookInfo.objects.filter(commentcount__gt=F('readcount'))
<QuerySet [<BookInfo: 射雕英雄传>, <BookInfo: 天龙八部>, <BookInfo: 笑傲江湖>]>
>>> 
Q对象

Q对象的对象相当于sql中的 or

>>> from django.db.models import Q
>>> BookInfo.objects.filter(Q(id=1)|Q(commentcount__gt=20))
<QuerySet [<BookInfo: 射雕英雄传>, <BookInfo: 天龙八部>, <BookInfo: 笑傲江湖>, <BookInfo: 雪山飞狐>]>
>>> 

Q对象前可以使用~操作符,表示非not。

>>> BookInfo.objects.filter(~Q(id=3))
<QuerySet [<BookInfo: 射雕英雄传>, <BookInfo: 天龙八部>, <BookInfo: 雪山飞狐>]>
>>> 

聚合查询

  • Max,Min,Sum,Count,Avg
  • 聚合函数需要和 aggregate配合使用
  • 模型.objects.aggregate(Xxx(‘字段’))

使用aggregate里面加上聚合函数

>>> BookInfo.objects.aggregate(Sum('readcount'))
{'readcount__sum': 126}
>>> 

排序

使用order_by对结果进行排序

# 默认升序
>>> BookInfo.objects.all().order_by('readcount')
<QuerySet [<BookInfo: 射雕英雄传>, <BookInfo: 笑傲江湖>, <BookInfo: 天龙八部>, <BookInfo: 雪山飞狐>]>


# 降序 在排序字段前加 - 
>>> BookInfo.objects.all().order_by('-readcount')
<QuerySet [<BookInfo: 雪山飞狐>, <BookInfo: 天龙八部>, <BookInfo: 笑傲江湖>, <BookInfo: 射雕英雄传>]>

关联查询

一对多 查询

在一的那方没有多的信息,所以需要反向查询

格式:关联模型类名小写_set.all() 获取关联的所有数据

>>> book = BookInfo.objects.get(pk=1)
>>> book.personinfo_set.all()
<QuerySet [<PersonInfo: 郭靖>, <PersonInfo: 黄蓉>, <PersonInfo: 黄药师>, <PersonInfo: 欧阳锋>, <PersonInfo: 梅超风>]>
>>> 

多对一 查询

在多的这方有外键属性,所以我们可以直接使用外键属性,查询到一的那方信息

>>> person = PersonInfo.objects.get(pk=1)
>>> person.book
<BookInfo: 射雕英雄传>
>>> 

关联过滤查询

一对多 过滤查询

一的那方没有多的属性,所以需要使用反向查询,我们的写的格式如下:

关联模型类名小写属性名条件运算符=值

>>> BookInfo.objects.filter(personinfo__id = 1)
<QuerySet [<BookInfo: 射雕英雄传>]>
>>> 

多对一 过滤查询

多的那方有一的那方属性,所以我们可以通过外键属性获取到一的那方属性,格式如下:

一模型类关联属性名一模型类属性名条件运算符=值

>>> PersonInfo.objects.filter(book_id = 1)
<QuerySet [<PersonInfo: 郭靖>, <PersonInfo: 黄蓉>, <PersonInfo: 黄药师>, <PersonInfo: 欧阳锋>, <PersonInfo: 梅超风>]>
>>> 


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值