django进阶之ORM单表增删改查

配置

默认情况下,django 使用 sqlite 作为数据库,相关的配置文件在项目的 settings.py文件 DATABASES 中配置。

使用 mysql,配置示例如下

1
2
3
4
5
6
7
8
9
10
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': 'books', #你的数据库名称
'USER': 'root', #你的数据库用户名
'PASSWORD': '', #你的数据库密码
'HOST': '', #你的数据库主机,留空默认为localhost
'PORT': '3306', #你的数据库端口
}
}

打开项目前需要保证 mysql 数据库已经安装且服务处于运行状态。
项目运行之后可能会出现 no module named MySQLdb报错信息

  • 原因
    默认情况下使用的是 MySQLdb 驱动,但是对 python3 的支持不太好,所以需要改用 PyMySQL
  • 处理
    安装 PyMySQL 驱动,然后在项目文件的 __init__.py里面写入
    1
    2
    import pymysql
    pymysql.install_as_MySQLdb()

数据库建表

建表相关操作在 models.py文件中定义,首先要导入 from django.db import models
默认情况下将会在表中创建字段id

  • 字段类型
    CharFileldIntegerFieldURLFieldEmailFieldBooleanFieldDateField
    对于 URLFieldEmailField等 数据库不存在的数据类型, django 会对输入的类型进行正则匹配的检查,确保符合相关标准。
  • 参数
    null 表示是否允许为空
    blank 通过 admin 管理页面
    verbose_name 字段的显示名称
    default 默认值
    max_length 字段最大长度
  • 表之间关系
    ForeignKey 外键,将会在to=指定的表中添加一个字段,存放该表的主键。
    下面的示例,将会在 class表中添加字段sch_id,保存的为 schopl表的id
    OneToOneField 一对一,将会在该表中添加一个字段,存放to=指定表的主键
    下面的示例,将会在number表中添加字段num_id,同时会为num_id添加一个唯一索引
    ManyToManyField 多对多,将会新建一个表,用于存放该表和to=指定表的主键
    下面的示例,将会在classuserinfo之外再新建一个表class_user
    字段user_iduser表主键,字段class_idclass表主键,同时为添加唯一索引uniq(class_id,userinfo_id)
  • __str__
    用于指定默认返回的值,若无默认返回class对象,否则返回该对象对应的值。
    建表示例
    1
    2
    3
    4
    5
    6
    7
    8
    9
    class UserInfo(models.Model):
    name = models.CharField(max_length=128, null=True, verbose_name='姓名')
    username=models.CharField(max_length=32, null=True)
    password=models.CharField(max_length=32, null=True)
    # number = models.IntegerField(default=0, verbose_name='学号')

    def __str__(self):
    return self.name
    # return self.name+self.username+self.password

OneToOneField 一对一示例

1
2
3
4
5
class Number(models.Model):
num = models.OneToOneField(to='UserInfo', verbose_name='学号')

def __str__(self):
return self.num

1
2
3
4
5
6
7
8
9
10
11
class School(models.Model):
name = models.CharField(max_length=128, null=True, blank=True, verbose_name='名字')
mac = models.URLField(max_length=128, default='1', verbose_name='地址')
email = models.EmailField(max_length=128, null=True, blank=True, verbose_name='邮箱')
true_false = models.BooleanField(max_length=128, null=True, blank=True, verbose_name='是否')
date = models.DateField(verbose_name='日期')
models.OneToOneField(to="Class", verbose_name='一对一关系')
cal = models.ForeignKey(to='Class', default=1) # 外键

def __str__(self):
return self.name

ManyToManyField 多对多示例

1
2
3
4
5
6
7
class Class(models.Model):
sch = models.ForeignKey(to='School', default=1) # ForeignKey外键示例
name = models.CharField(max_length=128, null=True, blank=True, verbose_name='名字')
user = models.ManyToManyField(to='UserInfo')

def __str__(self):
return self.name

完成建表操作之后在 Terminal 执行命令建表

1
2
python manage.py makemigrations
python manage.y migrate

单表数据操作

下面提到的 School 是在 models.py 中定义的类名称,作为示例

查询

  • 查询所有数据
    使用models.School.objects.all()查询所有数据

    1
    2
    3
    school_li = models.School.objects.all()
    for item in school_li:
    print(item, type(item), item.name)
  • get 方法查询
    使用 get 方法只适用于返回结果只有一行,不适用于多行

    1
    school = models.School.objects.get(id=6)
  • filter 方法查询

    1
    2
    3
    obj = models.School.objects.filter(name='aming_linux')  # 结果为QuerySet List
    obj1 = models.School.objects.filter(name='aming_linux').first() #取第一个结果
    obj2 = models.School.objects.filter(name='aming_linux').last() #取最后一个结果

当查询结果行数不确定,可以使用 filter 方法进行查询,查询结果为 QuerySet List
对得到的结果需要循环进行读取,同时特提供了first()last() 方法对结果进行处理,可直接返回查询结果
若传入参数为字典,可以使用下面的方式

1
2
dic = {'name': 'aming_linux'}
obj = models.School.objects.filter(**dic).first()

getfilter 方法,建议使用 filter

  1. get 返回结果为 QuerySet,filter 返回结果为 QuerySet List
  2. get 若无返回结果则报错,filter若无返回结果不会报错,返回空值

增加

增加数据使用create方法

1
2
3
dic = {'name': 'aming_linux'}
obj = models.School.objects.create(**dic)
obj1 = models.School.objects.create(name='aming_linux2')

返回结果为 class ,若定义了 __str__ 函数,则返回指定的对象

删除

删除数据使用delete方法

1
obj = models.School.objects.filter(**dic).delete()

返回结果示例 (1, {'demo.School': 1})
返回结果为元组,元组第一个参数是删除的总行数,第二个参数是字典,字典的 key 表示数据库表, value 表示删除的行数。若是跨表,字典中可能存在多对键值

修改

  • 方法1 update方法

    1
    obj = models.School.objects.filter(**dic).update(name='linux_aming')
  • 方法2 先查询再修改

    1
    2
    3
    obj = models.School.objects.get(name='linux_aming')
    obj.name = 'aming_linux'
    obj.save()

推荐使用方法1进行修改操作。

Recommended Posts