Django模型

本文详细介绍了Django模型如何映射数据库表,包括模型定义、字段类型、元属性、Manager管理器的使用,以及数据的增删改查操作。通过示例展示了模型字段的一对多、一对一和多对多关系,以及QuerySet的特性。同时,讲解了如何执行原始SQL语句,包括raw()方法和游标对象的使用。
摘要由CSDN通过智能技术生成


模型用来定义Django中数据的结构和行为,通常情况下每个Django模型映射数据库中的一张表。

Django模型—>数据库表

1、定义与使用模型

定义模型类

实例:定义books应用书籍信息模型类

模型类定义在应用的models.py文件中,并继承models.Model类

from django.db import models
class BookInfo(models.Model):          #魔法方法类模型 BookInfo
    name = models.CharField(max_length=20, verbose_name="名称")   #五个字段
    pub_date = models.DateField(verbose_name="发布日期")
    readcount = models.IntegerField(default=0, verbose_name="阅读量")
    commentcount = models.IntegerField(default=0, verbose_name="评论量")
    is_delete = models.BooleanField(default=False, verbose_name="逻辑删除")
    def __str__(self):       #将查询结果以字符串形式显示
        return self.name 

注册应用

若要将模型映射到数据库,需要先在settings.py文件中将包含该模型的应用安装到INSTALLED_APPS中,即在该项中添加一个表示应用名的元素。

INSTALLED_APPS = [
    ...
    'books',
]

映射

注册成功后,需要对模型中定义的模型类进行映射。映射分为两步:生成迁移文件和执行迁移文件。

  • 生成迁移文件

    就是通过ORM框架生成执行数据库操作所需的SQL语句。

    python manage.py makemigrations   #生成迁移文件
    

    image-20210415143717580

    若出现如图信息,则表名成功生成迁移文件。在books应用的migrations目录中:

    image-20210415143905778

    文件内容如下:

    from django.db import migrations, models
    class Migration(migrations.Migration):
        initial = True
        dependencies = [
        ]
        operations = [
            migrations.CreateModel(
                name='BookInfo',        #表示当前迁移数据的模型类名
                fields=[        #该列表中包含定义模型类中的字段
                    ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
                    ('name', models.CharField(max_length=20, verbose_name='名称')),
                    ('pub_date', models.DateField(verbose_name='发布日期')),
                    ('readcount', models.IntegerField(default=0, verbose_name='阅读量')),
                    ('commentcount', models.IntegerField(default=0, verbose_name='评论量')),
                    ('is_delete', models.BooleanField(default=False, verbose_name='逻辑删除')),
                ],
            ),
        ]
    

    若在定义模型类时没有指定主键,那么Django会自动创建id字段为主键。

  • 执行迁移文件

    就是执行迁移文件中的SQL语句。

    先创建一个数据库

    image-20210415160616265

    注:数据库名必须与配置文件settings.py中保持一致。

    环境搭建好之后运行下面的命令,结果如图:

    python manage.py migrate
    

    遇到的坑:

    ImportError: No module named ‘MySQLdb’ 参考文章

    image-20210415155839227

    然后在数据库中查看:

    image-20210415160807665

    所示的数据库表中出来books_bookinfo外,其他表都由Django内置的模型类映射而来。

    image-20210415155935192

    至此,模型类与数据库表映射完毕。


2、模型的字段

每个模型类的字段对应数据表中的一个字段。模型字段是模型类的属性,它自身也是一个类。

模型类字段---->数据表字段

字段类型

也就是字段的数据类型。

AutoField #用于定义可自增的整型字段

BooleanField #用于定义布尔类型的字段(Ture或False)

CharField #用于定义字符串类型的字段

DateField #定义YYYY-mm-dd格式的日期字段

TimeField #定义HH:MM[:ss[.uuuuuu]]格式的时间字段

DateTimeField #定义日期时间字段

EmailField #定义邮箱字段

FileField #用于上传文件字段

ImageField #用于上传图片文件

IntegerField #用于定义整型字段

TextField #用于定义大文本字段

关系字段

就是定义表之间的关系:一对多、一对一、多对多。

ForeignKey #定义一对多

实例:以国家和人为例,一个国家包含很多人,国家和人之间具有一对多关系。

from django.db import models
class Country(models.Model):
    country_code = models.CharField(max_length=20)
    country_name = models.CharField(max_length=20)
    class Meta:
        db_table="country"
class Person(models.Model):
    person_name = models.CharField(max_length=20)
    person_age = models.IntegerField(default=0)
    person_money = models.IntegerField(default=0)
    person_nation = models.ForeignKey(Country, on_delete=models.CASCADE)   #将person_nation设置为外键,与country表关联
    class Meta:
        db_table="person"

OneToOneField #定义一对一,它继承了ForeignKey

实例:以国家和总统为例,一个国家只能有一个总统,一个总统也只能属于一个国家,所以是一对一关系。

class President(models.Model)
	president_name = models.CharField(max_length=20)
    president_gender = models.CharField(max_length=10)
    president_nation = models.OneToOneField(Country)   #将president_nation字段设置为与Country相关联
    class Meta:
        db_table="president"

ManyToManyField #定义多对多

实例:教师与学生为多对多关系

class Teachers(models.Model):
    name = models.CharField(max_length=10)
    class Meta:
        db_table="teachers"
class Students(models.Model):
    name = models.CharField(max_length=10)
    classes = models.ManyToManyField(Teachers)  #将classes字段设置为与Teachers相关联
    class Meta:
        db_table="students"

3、模型的元属性

在模型类中添加内部类Meta的方式可以定义模型的元属性(如排序字段、数据表明、字段单复数等)

例如:

class BookInfo(models.Model):
    ...
    class Meta:
        db_table = 'tb_bookinfo'

常用元属性:

abstract # abstract=Ture则表示模型是抽象类。用来定义多个模型的共有信息,该模型不能被实例化,只能作为其他模型的基类

app_label # 指定当前模型所属的应用

ordering # 用于设置模型字段的排序方式

ordering = 'id'  #以id字段为升序排序
ordering = ['-id']  #以id字段为降序排序
ordering = ['id','score']  #如果只根据id无法为记录排序,再根据score进行升序排序

verbose_name # 用于设置显示在后台管理系统页面上的、直观可读的数据表名

verbose_name = "book"
verbose_name = "图书"

verbose_name_plural # 设置模型类在后台管理系统页面上显示的表名的复数形式

verbose_name_plural = "books"

若没指定则默认在verbose_name加上’s’作为复数形式,例如verbose_name值为book,那么模型类名的复数形式为books.


4、Manager管理器

管理器是Django模型进行数据查询操作的接口,每个模型都拥有至少一个管理器。

管理器名称

objects为每个模型类的默认管理器,但是可以改名,示例:

from django.db import models
class Person(models.Model):
    ...
    custom_objects = models.Manager()   # 重命名为custom_objects

使用Person.custom_objects.all()会返回一个包含所有Person对象的列表。

自定义管理器

在models.py文件中实例化自定义的Manager管理器,就可以在定义的模型中使用自定义的Manager管理器。自定义管理器通常有两种方式:一是添加额外的管理器方法,二是修改Manager的原始查询集。

1、添加额外的自定义管理器方法

就是为模型类增加“表级”功能。

class CountryManager(models.Manager):   #自定义管理器,其实就是一个类
    def conuntry_name_prefix(self):
        #查询所有结果
        all_countries = self.all()
        for country in all_countries:
            country.country_name = '国家:' + country.country_name
        return all_countries
class Country(models.Model):
    country_code = models.CharField(max_length=20)
    country_name = models.CharField(max_length=50)
    objects = CountryManager()        #指定管理器为CountryManager()
    class Meta:
        db_table = 'country'
    def __str__(self):
        return self.country_name

可以通过Country.objects.conuntry_name_prefix()查询所有国家名称。


5、数据的增删改查

添加数据

两种方法:

  • create()方法

    格式:create(self, **kwargs)

    实例:模型类BookInfo通过调用create()方法添加数据

    BookInfo.objects.create(name="骆驼祥子", readcount=100, pub_date="1937-1-2", is_delete=0, commentcount=70)
    
  • save()方法

    格式:save(force_insert=False, force_update=False, using=None, update_fileds=None)

    实例:创建模型类BookInfo的实例,调用save()方法保存实例数据,示例如下:

    bookinfo = BookInfo(name='围城', pub_date='1994-02-05', readcount=134, commentcount=100, is_delete=0)
    bookinfo.save()
    

查询数据

对象管理器提供了四个方法:

  • all()方法

    查询模型在数据库映射表中的所有记录,返回值是一个QuerySet对象(可迭代类似列表)

    实例:查询模型类BookInfo所对应数据表中所有的记录,示例如下

    all_info = BookInfo.objects.all()
    
  • filter()方法

    根据查询条件查询数据表,返回满足条件的数据,返回值是一个QuerySet对象。

    实例:筛选出id值大于3的记录,示例如下

    binfo = BookInfo.objects.filter(id__gt=3)
    
  • exclude()方法

    根据查询条件查询数据库,返回不满足条件的数据,返回值是一个QuerySet对象。

    实例:获取id值小于3的记录,示例如下

    ex_binfo = BookInfo.objects.exclude(id_gte=3)
    
  • get()方法

    返回符合条件的一条记录,返回值是一个模型对象

    实例:查询数据表books_bookinfo中id值为1的记录,示例如下

    binfo = BookInfo.objects.get(id=1)
    

删除数据

delect()方法

立即删除数据库中的记录,并返回删除记录的数量

binfo.delete()

更新数据

update()是对象管理器的方法,用于根据查询条件更新数据表的指定字段,并返回生效的行数。

格式:update(self, **kwargs)

实例:将模型类BookInfo对应的数据表中id为1的is_delete值修改为1,实例如下

BookInfo.objects.filter(id=1).update(is_delete=1)

6、QuerySet的使用

QuerySet是Django的数据查询集,表示从数据库中获取的对象集合。

多表查询

  • 正向查询:关联字段定义在当前表中,则从当前表查询关联表为正向查询
  • 反向查询:关联字段不在当前表中,则从当前表查询关联表为反向查询

1、一对多关系

以国家和人民为例,关联字段定义在模型Person中,那么使用Person对象查询Country对象为正向查询,使用Country对象查询Person对象为反向查询。

  • 正向查询

    格式:当前模型对象.关联字段.关联模型中要查询的字段

    实例:查询某人所属的国家,假设此人id为1

    p = Person.objects.get(id=1)
    p_country = p.person_nation.country_name
    

    person_nation为两模型的关联字段,country_name为country模型中的字段

  • 反向查询

    格式:当前模型对象.关联模型表名(小写)_set.all()

    实例:查询某国包含人员,假设该国家id为1,示例如下:

    c = Country.objects.get(id=1)
    p_country = c.person_set.all()
    

    以Country模型查询Person模型中的数据,其中关联模型为Person.

一对一关系和多对多关系与上面类似。

F对象和Q对象

如果在查询中需要比较表中的字段,可以使用django.db.models中的F对象;若查询条件为多个,则用Q对象。

  • F对象

    格式:F(字段名)

    实例:查询BookInfo模型类中,阅读量(readcount)大于评论量(commentcount)的图书。

    from django.db.models import F
    BookInfo.objects.filter(readcount__gt=F('commentcount'))
    #BookInfo.objects.filter(readcount=F('commentcount')*2)  #支持简单运算
    
  • Q对象

    格式:Q(属性名__运算符=值)

    实例:查询阅读量大于20且编号小于3的图书

    BookInfo.objects.filter(Q(readcount__gt=140)&Q(id__lte=5))
    #Q对象支持取反操作~Q(id=3)表示id不等与3
    

QuerySet的特性

惰性执行和缓存


7、执行原始SQL语句

两种方法:1、使用模型管理器的raw()方法;2、利用Django提供的默认数据库django.db.connection获取游标对象,再通过游标对象调用execute()方法执行SQL语句。

使用Manager.raw()方法

格式:Manager.raw(raw_query, params=None, translations=None)

实例:查询数据表person中所有数据,示例如下:

person = Person.objects.raw("select * from person")

等价于Person.objects.all()

raw()方法将查询语句中的字段映射到模型字段,因此raw()方法中字段的顺序并不影响查询出的结果,如:

Person.objects.raw("select id,person_age,person_name from person")
Person.objects.raw("select person_age,id,person_name from person") 
#二者查询结果一致

注:raw()方法的查询语句中必须包含主键

示例:

Person.objects.raw("select pk as id,p_age as person_age,p_name as person_name from person")

代码与数据分离:

  • translations方式

    query_map = {"pk:id","p_age:person_age","p_name:person_name"}
    Person.objects.raw("select * from person", translations=query_map)  #传字段
    
    person = Person.objects.raw("select * from person")[0] #raw()方法支持索引
    
  • params方式

    param = ['person_name']
    p_name = Person.objects.raw("select id,%s from person", param)  #传字段
    
    param = {"id"=1}
    p_name = Person.objects.raw("select * from person where id=%(id)s", param)  #传参
    

利用游标对象

from django.db import connection
conn = connection.cursor()  #获取游标对象
conn.execute('select * from person')   #直接执行语句
conn.fetchone()  #查询一条语句
conn.fetchall()  #查询所有记录
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值