Django - ORM数据库操作 - 表结构、单表操作

目录

一、ORM (对象关系映射 Object Relational Mapping)

二、表结构的创建和修改

 1、表结构的创建

1-1 setting内建立数据库连接

1-2 models.py 内创建模型

1-3 migrations 内 __init__.py文件修改

1-4 迁移命令的两种执行方式

2、表结构的修改

2-1 增加字段

2-2 删除字段

2-3 修改字段

3、模型内字段类型

4、字段参数

5、元信息

三、单表记录操作

1、在py文件中调用Django环境(可用于orm记录操作语言的测试)

2、查(API)

-  filter() - 返回queryset对象

- 基于filter的双下划线模糊查询

- values(*field):返回特殊的queryset类型

3、增(两种方式)

方式一、create方法创建记录对象

方式二、创建对象,save方法保存

4、改(两种方式)

1、方式一:update()方法

2、方式二、修改对象,save 保存

5、删(delete())

1、所有对象删除

2、根据记录删除


一、ORM (对象关系映射 Object Relational Mapping)

介绍:对pymysql模块的二次封装,进行操作mysql

优点:

  1. 提高了开发效率
  2. 可以使用代码创建表、并对表进行增删改查操作

缺点:

  1. 降低了执行效率
  2. 不可以自主创造数据库

二、表结构的创建和修改

 1、表结构的创建

1-1 setting内建立数据库连接

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'lqz',
        'USER': 'root',
        'PASSWORD': '123456',
        'HOST': '127.0.0.1',
        'PORT': 3306,
        'ATOMIC_REQUEST': True,
        'OPTIONS': {
            "init_command": "SET storage_engine=MyISAM",
        }
    }
}

'''
'NAME':要连接的数据库,连接前需要创建好
'USER':连接数据库的用户名
'PASSWORD':连接数据库的密码
'HOST':连接主机,默认本机
'PORT':端口 默认3306
'ATOMIC_REQUEST': True,
设置为True统一个http请求对应的所有sql都放在一个事务中执行(要么所有都成功,要么所有都失败)。
是全局性的配置, 如果要对某个http请求放水(然后自定义事务),可以用non_atomic_requests修饰器 
'OPTIONS': {
             "init_command": "SET storage_engine=MyISAM",
            }
设置创建表的存储引擎为MyISAM,INNODB
'''

1-2 models.py 内创建模型

from django.db import models

# 一个类就是一个表
class User(models.Model):
    # 自增int类型,是主键
    id = models.AutoField(primary_key=True)
    # name 是一个varchar类型,长度是32
    name = models.CharField(max_length=32)
    pwd = models.CharField(max_length=32)

1-3 项目 内 __init__.py文件修改

注意:

  • 若只是在app文件夹下的init文件添加,则只能当前app内使用mysqldb
  • 若在总项目文件夹下的init文件中添加,所有app的数据库都使用mysqldb
import pymysql
pymysql.install_as_MySQLdb()

1-4 迁移命令的两种执行方式

  •  方式一、终端命令
    python3 manage.py makemigrations  --- 记录数据库的修改记录
    python3 manage.py migrate ---- 数据修改同步数据库
  • 方式二、pycharm工具栏操作
    工具栏 -- tools--->Run manage.py Task
    makemigrations
    migrate
  • 注意:

         1 数据库迁移记录都在 app01下的migrations里
            2 使用showmigrations命令可以查看没有执行migrate的文件(python manage.py showmigrations)

            3  makemigrations是生成一个文件,migrate是将更改提交到数据量

 

2、表结构的修改

2-1 增加字段

from django.db import models

# 一个类就是一个表
class User(models.Model):
    # 自增int类型,是主键
    id = models.AutoField(primary_key=True)
    # name 是一个varchar类型,长度是32
    name = models.CharField(max_length=32)
    pwd = models.CharField(max_length=32)

    # 在原有结构上添加字段,必须带有默认值
    phone=models.CharField(max_length=64,default='120')

2-2 删除字段

from django.db import models

# 一个类就是一个表
class User(models.Model):
    # 自增int类型,是主键
    id = models.AutoField(primary_key=True)
    # name 是一个varchar类型,长度是32
    name = models.CharField(max_length=32)
    pwd = models.CharField(max_length=32)

    # 在原有结构上注释字段
    # phone=models.CharField(max_length=64,default='120')


''' 文件修改完成,执行两句迁移命令 '''

2-3 修改字段

from django.db import models

# 一个类就是一个表
class User(models.Model):
    # 自增int类型,是主键
    id = models.AutoField(primary_key=True)
    # name 是一个varchar类型,长度是32
    name = models.CharField(max_length=32)
    pwd = models.CharField(max_length=32)

    # 在原有结构上修改结构内容
    phone=models.CharField(max_length=64,default='11111111111')


''' 文件修改完成,执行两句迁移命令 '''

 

3、模型内字段类型

  • AutoField(Field) - int自增列,必须填入参数 primary_key=True
  • BigAutoField(AutoField) - bigint自增列,必须填入参数 primary_key=True
    //注:当model中如果没有自增列,则自动会创建一个列名为id的列
    from django.db import models
    
    class UserInfo(models.Model):
        # 自动创建一个列名为id的且为自增的整数列
        username = models.CharField(max_length=32)
    
    class Group(models.Model):
        # 自定义自增列
        nid = models.AutoField(primary_key=True)
        name = models.CharField(max_length=32)
  • mallIntegerField(IntegerField): - 小整数 -32768 ~ 32767

  • PositiveSmallIntegerField(PositiveIntegerRelDbTypeMixin, IntegerField) - 正小整数 0 ~ 32767

  • IntegerField(Field) - 整数列(有符号的) -2147483648 ~ 2147483647

  • PositiveIntegerField(PositiveIntegerRelDbTypeMixin, IntegerField) - 正整数 0 ~ 2147483647

  • BigIntegerField(IntegerField): - 长整型(有符号的) -9223372036854775808 ~ 9223372036854775807
     

    //自定义无符号整数字段
    
    class UnsignedIntegerField(models.IntegerField):
    def db_type(self, connection):
    return 'integer UNSIGNED'
    
    '''
    PS: 返回值为字段在数据库中的属性,Django字段默认的值为:
    'AutoField': 'integer AUTO_INCREMENT',
    'BigAutoField': 'bigint AUTO_INCREMENT',
    'BinaryField': 'longblob',
    'BooleanField': 'bool',
    'CharField': 'varchar(%(max_length)s)',
    'CommaSeparatedIntegerField': 'varchar(%(max_length)s)',
    'DateField': 'date',
    'DateTimeField': 'datetime',
    'DecimalField': 'numeric(%(max_digits)s, %(decimal_places)s)',
    'DurationField': 'bigint',
    'FileField': 'varchar(%(max_length)s)',
    'FilePathField': 'varchar(%(max_length)s)',
    'FloatField': 'double precision',
    'IntegerField': 'integer',
    'BigIntegerField': 'bigint',
    'IPAddressField': 'char(15)',
    'GenericIPAddressField': 'char(39)',
    'NullBooleanField': 'bool',
    'OneToOneField': 'integer',
    'PositiveIntegerField': 'integer UNSIGNED',
    'PositiveSmallIntegerField': 'smallint UNSIGNED',
    'SlugField': 'varchar(%(max_length)s)',
    'SmallIntegerField': 'smallint',
    'TextField': 'longtext',
    'TimeField': 'time',
    'UUIDField': 'char(32)',
    '''
  • BooleanField(Field) - 布尔值类型

  • NullBooleanField(Field): - 可以为空的布尔值

  •  CharField(Field) - 字符类型 - 必须提供max_length参数, max_length表示字符长度

  • TextField(Field) - 文本类型

  • EmailField(CharField): - 字符串类型,Django Admin以及ModelForm中提供验证机制

  • IPAddressField(Field) - 字符串类型,Django Admin以及ModelForm中提供验证 IPV4 机制

  • GenericIPAddressField(Field) - 字符串类型,Django Admin以及ModelForm中提供验证 Ipv4和Ipv6
      - 参数:
         protocol,用于指定Ipv4或Ipv6, 'both',"ipv4","ipv6"
         unpack_ipv4, 如果指定为True,则输入::ffff:192.0.2.1时候,可解析为192.0.2.1,开启刺功能,需要 protocol="both"

  • URLField(CharField) - 字符串类型,Django Admin以及ModelForm中提供验证 URL

  • SlugField(CharField) - 字符串类型,Django Admin以及ModelForm中提供验证支持 字母、数字、下划线、连接符(减号)

  • CommaSeparatedIntegerField(CharField) - 字符串类型,格式必须为逗号分割的数字

  • UUIDField(Field) - 字符串类型,Django Admin以及ModelForm中提供对UUID格式的验证

  • FilePathField(Field) - 字符串,Django Admin以及ModelForm中提供读取文件夹下文件的功能
    - 参数:
    path,                      文件夹路径
    match=None,                正则匹配
    recursive=False,           递归下面的文件夹
    allow_files=True,          允许文件
    allow_folders=False,       允许文件夹

  • FileField(Field) - 字符串,路径保存在数据库,文件上传到指定目录
    - 参数:
    upload_to = ""      上传文件的保存路径
    storage = None      存储组件,默认django.core.files.storage.FileSystemStorage

  • ImageField(FileField) - 字符串,路径保存在数据库,文件上传到指定目录
    - 参数:
    upload_to = ""      上传文件的保存路径
    storage = None      存储组件,默认
               django.core.files.storage.FileSystemStorage
    width_field=None,   上传图片的高度保存的数据库字段名(字符串)
    height_field=None   上传图片的宽度保存的数据库字段名(字符串)

  • DateTimeField(DateField) - 日期+时间格式 YYYY-MM-DD HH:MM[:ss[.uuuuuu]][TZ]

  • DateField(DateTimeCheckMixin, Field) - 日期格式      YYYY-MM-DD

  • TimeField(DateTimeCheckMixin, Field) - 时间格式      HH:MM[:ss[.uuuuuu]]

  • DurationField(Field) - 长整数,时间间隔,数据库中按照bigint存储,ORM中获取的值为datetime.timedelta类型

  • FloatField(Field) - 浮点型

  • DecimalField(Field) - 10进制小数
    - 参数:
    max_digits,小数总长度
    decimal_places,小数位长度

    BinaryField(Field) - 二进制类型

4、字段参数

  • (0) null 如果为True,Django 将用NULL 来在数据库中存储空值。 默认值是 False.
  • (1) blank 如果为True,该字段允许不填。默认为False。 要注意,这与 null 不同。null纯粹是数据库范畴的,而 blank 是数据验证范畴的。 如果一个字段的blank=True,表单的验证将允许该字段是空值。如果字段的blank=False,该字段就是必填的。
  • (2) default 字段的默认值。可以是一个值或者可调用对象。如果可调用 ,每有新对象被创建它都会被调用。
  • (3) primary_key 如果为True,那么这个字段就是模型的主键。如果你没有指定任何一个字段的primary_key=True, Django 就会自动添加一个IntegerField字段做为主键,所以除非你想覆盖默认的主键行为, 否则没必要设置任何一个字段的primary_key=True。
  • (4) unique 如果该值设置为 True, 这个数据字段的值在整张表中必须是唯一的
  • (5) choices 由二元组组成的一个可迭代对象(例如,列表或元组),用来给字段提供选择项。 如果设置了choices ,默认的表单将是一个选择框而不是标准的文本框,<br>而且这个选择框的选项就是choices 中的选项。

 

5、元信息

 class UserInfo(models.Model):
        nid = models.AutoField(primary_key=True)
        username = models.CharField(max_length=32)
        class Meta:
            # 数据库中生成的表名称 默认 app名称 + 下划线 + 类名
            db_table = "table_name"

            # 联合索引
            index_together = [
                ("pub_date", "deadline"),
            ]

            # 联合唯一索引
            unique_together = (("driver", "restaurant"),)

            # admin中显示的表名称
            verbose_name

            # verbose_name加s
            verbose_name_plural

三、单表记录操作

1、在py文件中调用Django环境(可用于orm记录操作语言的测试)

import os

if __name__ == '__main__':
    os.environ.setdefault("DJANGO_SETTINGS_MODULE", "day76orm.settings")
    import django

    django.setup()

    from app01 import models
    
    # 记录的操作
    book=models.Book.objects.create(name='红楼梦',price=23.8,publish='人民出版社',author='曹雪芹',create_data='2018-09-17')
    print(book.name)
    
    …… ……

2、查(API)

总结:

  • python数据精度存在盲点,使用查询数字类型的时候,注意转换的sql语句所传输的数字是否精确
  • 可以对queryset对象使用.query方法调用,可以查询最终传输到数据的纯生sql语句
  • 查询得到的queryset可以进行后续的查询方法,通过.进行调用
all()  - models.User.objects.all() 查询所有结果,得到的是一个queryset对象(列表),列表内存储对象。

filter(**kwargs)
  -- 
models.User.objects.filter(name='红楼梦').first()

包含与所给筛选条件匹配的对象,返回queryset对象

get(**kwargs)

-- models.User.objects.get(name='红楼梦')

返回筛选条件匹配的对象,且返回结果有且只有一个;若存在符合对象超过一个或者不存在,抛出异常

exclude(*field)

  -- models.User.objects.exclude(name='红楼梦')

包含了所有与筛选条件不匹配的对象,返回queryset对象

order_by(*field)

  -- models.User.objects.all.order_by('id')

  -- models.User.objects.all.order_by('-id','name')

对查询结果排序 ('-id'),默认升序,加- 降序。多个过滤条件可以同时共用,返回queryset对象

reverse()

  -- models.User.objects.all().reverse()

对查询结果反向排序,返回queryset对象

count()

  -- models.User.objects.all().count()

queryset为调用对象,返回数据库中匹配查询(QuerySet)的对象数量

first()

 - models.User.objects.first()

返回第一条记录

last()

  -models.User.objects.last()

返回最后一条记录
exists() 若queryset包含数据,返回True,否则False,返回布尔类型

values(*field)

  -- models.User.objects.all().values('name')

返回一个ValueQuerySet - 一个特殊的QuerySet,运行后得到一个可迭代的字典序列
<QuerySet [{'name': '红楼梦'}, {'name': '水浒传'}, {'name': '西游记'}]>

values_list(*field)

-- models.User.objects.all().values_list('name','id')

同values()相似,返回一个元组列表
<QuerySet [('红楼梦', Decimal('23.80')), ('水浒传', Decimal('99.80')), ('西游记', Decimal('73.80'))]>

distinct() 

-- models.User.objects.all().distinct()

-- models.Book.objects.all().values('name').distinct()

从返回的结果中剔除重复记录;distinct seletc * 的时候没有意义,只要存在唯一的字段(id段等)都没有去重意义

-  filter() - 返回queryset对象

# 查询名字叫西游记的这本书,返回单个对象
ret = models.Book.objects.filter(name='西游记').first()
print(ret)
print(type(ret))

# 支持类列表的查询方式
ret = models.Book.objects.filter(name='西游记')[1]

# 类列表的查询方式,不支持负数,只支持正数
ret = models.Book.objects.filter(name='西游记')[-1]

# filter内可以传多个参数,用逗号分隔,他们之间是and的关系
# 返回queryset

# 价格使用字符串,防止精度不准确,导致无法进行查询
ret = models.Book.objects.filter(name='西游记', price='73.8')
print(ret)
print(type(ret))

# ret.query -->queryset对象打印sql
print(ret.query)

'''
SELECT
	`app01_book`.`id`,
	`app01_book`.`name`,
	`app01_book`.`price`,
	`app01_book`.`publish`,
	`app01_book`.`author`,
	`app01_book`.`create_data`
FROM
	`app01_book`
WHERE
	(
		`app01_book`.`name` = 西游记
		AND `app01_book`.`price` = 73.8
	)
'''

- 基于filter的双下划线模糊查询

# filter(字段名__gt='') ---- 大于
# 查询价格大于89 的书
ret=models.Book.objects.filter(price__gt='89')

# filter(字段名__lt='') ---- 小于
# 查询价格小于89 的书
ret=models.Book.objects.filter(price__lt='89')

# ret=models.Book.objects.filter(price__lt='89',price='89')  --- 错误的小于等于
# filter(字段名__lte='') ---- 小于等于
ret=models.Book.objects.filter(price__lte='89')
# filter(字段名__gte='') ---- 大于等于
ret = models.Book.objects.filter(price__gte='89')

# filter(字段名__in='') ---- 字段存在列表中
ret=models.Book.objects.filter(price__in=['23.8','89','100'])

# filter(字段名__range='') ---- 字段数据在范围内(between and)
ret=models.Book.objects.filter(price__range=[50,100])

# filter(字段名__contains='') ---- 字段数据包含内容 模糊查询 like % %
# 查询名字有'%红%'的书
ret=models.Book.objects.filter(name__contains='红')

# filter(字段名__icontains='') ---- 字段数据包含内容,并且忽略大小写 模糊查询 like % %
# 查询名字带p的书,忽略大小写
ret=models.Book.objects.filter(name__icontains='P')

# filter(字段名__startswith='') ---- 字段数据以内容开头
ret=models.Book.objects.filter(name__startswith='红')

# filter(字段名__endswith='') ---- 字段数据以内容结尾
ret=models.Book.objects.filter(name__endswith='梦')

# filter(字段名__year='') ---- 查询字段内容以指定年份查询
ret=models.Book.objects.filter(create_data__year='2018')

# filter(字段名__month='') ---- 查询字段内容以指定月份查询
ret = models.Book.objects.filter(create_data__month='9')

# filter(字段名__day='') ---- 查询字段内容以指定日期查询
ret = models.Book.objects.filter(create_data__day='8')

 

- values(*field):返回特殊的queryset类型

# values(*field): queryset对象里套字典


ret=models.Book.objects.all().values('name','price')

print(ret)
# <QuerySet [{'name': '红楼梦', 'price': Decimal('23.80')}, {'name': '水浒传', 'price': Decimal('99.80')}, {'name': '西游记', 'price': Decimal('73.80')}]>
print(ret[1])
# {'name': '水浒传'}
print(ret.query)
'''
SELECT
	`app01_book`.`name`,
	`app01_book`.`price`
FROM
	`app01_book`
'''



ret=models.Book.objects.all().values('name')

print(ret)
# <QuerySet [{'name': '红楼梦'}, {'name': '水浒传'}, {'name': '西游记'}]>
print(ret[1])
# {'name': '水浒传'}
print(ret.query)
'''
SELECT
	`app01_book`.`name`
FROM
	`app01_book`
'''

 

3、增(两种方式)

方式一、create方法创建记录对象

name=request.POST.get('name')
pwd=request.POST.get('password')
addr=request.POST.get('addr')
user=models.User.objects.create(name=name,password=pwd,address=addr)

方式二、创建对象,save方法保存

name=request.POST.get('name')
pwd=request.POST.get('password')
addr=request.POST.get('addr')
user=models.User(name=name,password=pwd,address=addr)
user.save()

4、改(两种方式)

1、方式一:update()方法

注意:update方法对于任何结果集(queryset)有效,可以同时更新多条记录,使用update()方法会返回一个整数数值,表示受影响的记录条数。

name=request.POST.get('name')
pwd=request.POST.get('password')
addr=request.POST.get('addr')
models.User.objects.filter(id=id).update(name=name,password=pwd,address=addr)

2、方式二、修改对象,save 保存

book = models.Book.objects.filter(name='西游记').first()
book.price=89
book.save()

 

5、删(delete())

1、所有对象删除

models.User.objects.all().delete()

2、根据记录删除

id = request.GET.get('id')
ret = models.User.objects.filter(id=id).delete()

ret = models.Book.objects.filter(name='西游记').first()
ret.delete()

猜你喜欢

转载自blog.csdn.net/qq_33961117/article/details/83864629