ORM

本文深入讲解了ORM技术在Python Django框架中的应用,详细介绍了各种数据类型及其在数据库中的映射,如AutoField、BigIntegerField等,并演示了如何通过Python脚本进行数据库操作,包括查询、过滤、排序等。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

ORM
ORM

class Person(models.Model):
    pid = models.AutoField(primary_key=True)  # 主键
    name = models.CharField(max_length=32)  # varchar(32)
    age = models.IntegerField()  # 整型 -21亿-21亿
    # birth = models.DateTimeField(auto_now_add=True) # 每当新增数据时 自动保存当前时间
    birth = models.DateTimeField(auto_now=True)  # 每当新增和编辑数据时 自动保存当前时间

字段类型

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)

    SmallIntegerField(IntegerField):
        - 小整数 -3276832767

    PositiveSmallIntegerField(PositiveIntegerRelDbTypeMixin, IntegerField)
        - 正小整数 032767

    IntegerField(Field)
        - 整数列(有符号的) -21474836482147483647

    PositiveIntegerField(PositiveIntegerRelDbTypeMixin, IntegerField)
        - 正整数 02147483647

    BigIntegerField(IntegerField):
        - 长整型(有符号的) -92233720368547758089223372036854775807

    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)
        - 二进制类型

使用Django的admin创建超级用户

D:\python\orm_base>python manage.py createsuperuser
Username (leave blank to use 'xiefei'): root1234
Email address:
Password:
Password (again):
The password is too similar to the username.
Bypass password validation and create user anyway? [y/N]: y
Superuser created successfully.

urls.py中包含

urlpatterns = [
    path('admin/', admin.site.urls),
]

setting.py中包含

INSTALLED_APPS = [
    'django.contrib.admin', # 必须有
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'app01.apps.App01Config'
]

然后再网页访问

  • http://127.0.0.1:8000/admin/

在app下的admin.py下注册model

from django.contrib import admin
from app01 import models

# Register your models here.

admin.site.register(models.Person)

未定义__str__(self):

定义__str__(self):class Person(models.Model):
    pid = models.AutoField(primary_key=True)  # 主键
    name = models.CharField(max_length=32)  # varchar(32)
    age = models.IntegerField()  # 整型
    # birth = models.DateTimeField(auto_now_add=True) # 每当新增数据时 自动保存当前时间
    birth = models.DateTimeField(auto_now=True)  # 每当新增和编辑数据时 自动保存当前时间

    def __str__(self):
        return "{}-{}".format(self.name, self.age)
  • 用python脚本执行数据库相关炒作操作
  • 创建一个orm操作的文件夹
  • 创建python文件
  • 从manage.py中导入系统环境配置文件设置环境配置变量
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'orm_base.settings')
# !/usr/bin/env python
# -*- coding: UTF-8 -*-
# 作者    :xiefei
# 时间    :2020/8/2 12:05
# IDE    :PyCharm

import os

if __name__ == '__main__':
    # 下面的 cms_book 改成你当前的项目名称
    os.environ.setdefault("DJANGO_SETTINGS_MODULE", "orm_base.settings")
    import django

    django.setup()
    from app01 import models # 必须在项目加载后导入

    # all 查询所有的数据 QuerySet 对象列表 [对象,对象]
    ret = models.Person.objects.all()
    '''
    调用:
    def __repr__(self):
    return '<%s: %s>' % (self.__class__.__name__, self)
    也可以重新定义
    def __repr__(self):
    return "{}-{}".format(self.name, self.age)
    '''
    print(ret)
    '''
    打印对象的时候会调用__str__(self)方法,
    因为先前已经重新定义了
    def __str__(self):
    return "{}-{}".format(self.name, self.age)
    所以打印格式为xiefei-22
    默认:
    def __str__(self):
    return '%s object (%s)' % (self.__class__.__name__, self.pk)
    打印:Person object (3)
    '''
    # get 获取一个且唯一的数据 对象 没用或者多个数据就报错
    ret1 = models.Person.objects.get(name="xiefei")
    print(ret1)
    # filter 获取满足条件的多条数据 对象列表 [对象 对象] 没用为空
    ret2 = models.Person.objects.filter(age=22)
    print(ret2)
    # 排序 默认升序 降序:字段前加- 可以多个字段排序,
    ret3 = models.Person.objects.all().order_by("age", "-pid")
    print(ret3)
    # reverse 反转 对已经排序的对像列表进行排序
    ret4 = models.Person.objects.all().order_by("pid").reverse()
    print(ret4)
    # values() QuerySet[{字段:值},{...}] 把每一个对象编程字典类型 {字段: 值}
    # 可以指定字段
    ret5 = models.Person.objects.all().values("pid", "name")
    # print(ret5)
    print("-------------------------")
    for i in ret5:
        print(i)
    # 只获取字段对应的值 不获取字段名 ()元组类型
    ret6 = models.Person.objects.all().values_list("pid", "name")
    for i in ret6:
        print(i)
    # distinct 去重
    ret7 = models.Person.objects.values("age").distinct()
    print(ret7)
    # count 计数
    ret8 = models.Person.objects.all().count()  # 效率跟高
    ret81 = len(models.Person.objects.all())
    print(models.Person.objects.filter(age=22).count())
    print(ret8, ret81)
    # first() 获取第一个元素
    ret9 = models.Person.objects.all().first()
    print(ret9)
    # last() 最后一个
    ret10 = models.Person.objects.all().last()
    print(ret10)
    # exists() 判断数据库是否有这条数据
    ret11 = models.Person.objects.filter(pid=3).exists()
    print(ret11)
    # 排除 exclude()
    ret12 = models.Person.objects.exclude(pid=1)
    print(ret12)
    '''
    返回对象列表QuerySet:
        all
        filter
        exclude
        order_by
        reverce
        values[{}.{}]
        values_list[(),()]
        distinct
        
    返回对象:
        get
        first
        last
    返回数字:
        count
    返回bool:
        exists
    '''

单表的双下划线

models.Tb1.objects.filter(id__lt=10, id__gt=1)   # 获取id大于1 且 小于10的值
models.Tb1.objects.filter(id__lte=10, id__gte=1)   # 获取id大于党羽1 且 小于等于10的值
models.Tb1.objects.filter(id__in=[11, 22, 33])   # 获取id等于11、22、33的数据
models.Tb1.objects.exclude(id__in=[11, 22, 33])  # not in
 
models.Tb1.objects.filter(name__contains="ven")  # 获取name字段包含"ven"的
models.Tb1.objects.filter(name__icontains="ven") # icontains大小写不敏感
 
models.Tb1.objects.filter(id__range=[1, 3])      # id范围是1到3的,等价于SQL的bettwen and
 
类似的还有:startswith,istartswith, endswith, iendswith 

date字段还可以:
models.Class.objects.filter(first_day__year=2017)
models.Class.objects.filter(first_day__year=2017)

外键 (一对多关系)

from django.db import models


# Create your models here.

class Person(models.Model):
    pid = models.AutoField(primary_key=True)  # 主键
    name = models.CharField(max_length=32)  # varchar(32)
    age = models.IntegerField()  # 整型
    # birth = models.DateTimeField(auto_now_add=True) # 每当新增数据时 自动保存当前时间
    birth = models.DateTimeField(auto_now=True)  # 每当新增和编辑数据时 自动保存当前时间

    def __str__(self):
        return "{}-{}-{}".format(self.pid, self.name, self.age)

    # __repr__ = __str__
    def __repr__(self):
        return "{}-{}-{}".format(self.pid, self.name, self.age)


class Press(models.Model):
    def __str__(self):
        return "Press object:{}-{}".format(self.id, self.name)

    def __repr__(self):
        return "Press object:{}-{}".format(self.id, self.name)

    name = models.CharField(max_length=32, verbose_name='出版社名称')


class Book(models.Model):
    name = models.CharField(max_length=32, verbose_name='书籍名称')
    press = models.ForeignKey(Press, on_delete=models.CASCADE, related_name="books")
    # 设置反向查询的名称 默认类 名小写_set
    # related_query_name="" 字段查询名称

    def __str__(self):
        return "Book object:{}-{}".format(self.id, self.name)

    def __repr__(self):
        return "Press object:{}-{}".format(self.id, self.name)
# !/usr/bin/env python
# -*- coding: UTF-8 -*-
# 作者    :xiefei
# 时间    :2020/8/2 17:17
# IDE    :PyCharm
import os
import django

os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'orm_base.settings')
django.setup()
if __name__ == '__main__':
    from app01 import models
    # 基于对象的查询
    # 正向查询
    book_obj = models.Book.objects.get(id=1)
    print(book_obj.id)
    print(book_obj.press_id)
    # 反向查询
    # 未有指定 related_name 默认 类名小写_set
    press_obj = models.Press.objects.get(id=1)
    print(press_obj.books, type(press_obj.books)) # 默认类名小写_set
    print(press_obj.books.all())

    # 基于字段的查询
    ret3 = models.Book.objects.filter(name="资治通鉴")
    print(ret3)
    # 通过子表查询父表数据
    ret4 = models.Book.objects.filter(press__name="新华出版社")
    # ret4 = models.Book.objects.filter(press__name__id="新华出版社")
    print(ret4)
    # 未有指定 related_name 默认 类名小写__
    ret5 = models.Press.objects.filter(books__name='资治通鉴')
    print(ret5)

外键多对多

# 多对多操作 和外键的操作一样
author_obj = models.Author.objects.get(id=1)
print(author_obj.book)
print(author_obj.book.all())
book_obj1 = models.Book.objects.get(id=1)
print(book_obj.author_set.all())
# 通过书籍表查询作者
print(models.Book.objects.filter(author__name='xiefei'))
# 通过book表设置作者书籍 set

Django 框架get()和filter()返回值的区别 先上官方文档!

filter(**kwargs)
返回包含与给定查找参数匹配的对象的新查询集。
简单来说,返回一个又对象组成的查询集合
get(**kwargs)
返回与给定查找参数匹配的对象,该对象应采用字段查找中描述的格式。
例子
例如在Model中有一个Order类,包含一个id字段,输入 id 为2019 字段的 id
1.get()方法

orders = Orders.objects.get(id=20190003)
print(order)

1
2


先查看orders是什么,结果为
Orders object

1
按照官方文档所说的,他是一个对象没错,可以直接用点操作进行字段取值
print(order.id)

1
结果就是20190003

2.filter() 方法

orders = Orders.objects.filter(id=20190003)
print(order)

1
2
先查看orders是什么
<QuerySet [<Orders:Orders object>]>

1
我认为 前面的QuerySet 是告诉我们这个是一个查询集,真正的查询集内容是列表[]里面的东西,<>表示查询集的范围。[]中的Orders同理。这个时候我们发现[]中的东西就是get()方法所获得东西,因此只需要取order[0]即可,打印order[0]可以看见
Orders object

1
因此,order[0].id.也就能获得20190003
备注: 如果filter查询返回的结果多条,结果为
<QuerySet [<Orders:Orders object><Orders:Orders object><Orders:Orders object>]>

1
本质上看起来为一个列表
总结:get()返回的是一个对象,filter()返回的是由对象组成的列表,称为查询集
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值