Django之ORM操作

双下划线查询

数据准备

class Staff(models.Model):
    name = models.CharField(max_length=32)
    age = models.IntegerField()
    salary = models.DecimalField(max_digits=8, decimal_places=2)
    recruit_time = models.DateField(auto_now=True)

    def __str__(self):
        return "%s-对象" % self.name
models.Staff.objects.create(name='linda', age=22, salary=25000.00)
models.Staff.objects.create(name='rose', age=24, salary=15000.00)
models.Staff.objects.create(name='frank', age=32, salary=35000.00)
models.Staff.objects.create(name='laurence', age=24, salary=25000.00)
models.Staff.objects.create(name='steve', age=42, salary=15000.00)
models.Staff.objects.create(name='july', age=32, salary=35000.00)
models.Staff.objects.create(name='sam', age=27, salary=42000.00)
models.Staff.objects.create(name='tom', age=33, salary=28000.00)
models.Staff.objects.create(name='Simon', age=43, salary=45000.00)

具体操作

# 一、查询年龄小于等于27的员工
staff_obj = models.Staff.objects.filter(age__lte=27)
print(staff_obj)
	"""
    __gt         大于
    __lt         小于
    __gte        大于等于
    __lte        小于等于
    """
# 二、查询年龄是24、32、42的员工
staff_obj = models.Staff.objects.filter(age__in=[14, 32, 42])
print(staff_obj
	"""
    __in         成员运算
    """
# 三、查询年龄在25到30之间的员工
 staff_obj = models.Staff.objects.filter(age__range=[25, 30])
 print(staff_obj)
	"""
    __range      范围查询
    """
# 四、查询姓名中包含字母s的员工
 staff_obj = models.Staff.objects.filter(name__contains='s')
 print(staff_obj)  # <QuerySet [<Staff: rose-对象>, <Staff: steve-对象>, <Staff: sam-对象>]>
 staff_obj = models.Staff.objects.filter(name__icontains='s')
 print(staff_obj)  # <QuerySet [<Staff: rose-对象>, <Staff: steve-对象>, <Staff: sam-对象>, <Staff: Simon-对象>]>
	"""
    __contains      区分大小写
    __icontains     忽略大小写
    """
# 五、查询姓名中首字母为j的员工
      staff_obj = models.Staff.objects.filter(name__startswith='j')
      print(staff_obj)  # <QuerySet [<Staff: july-对象>]>
# 六、查询姓名中尾字母为e的员工
      staff_obj = models.Staff.objects.filter(name__endswith='e')
      print(staff_obj)  # <QuerySet [<Staff: rose-对象>
# 七、查询姓名中s开头m结尾的员工
      staff_obj = models.Staff.objects.filter(name__regex='^s.*m$')
      print(staff_obj)  # <QuerySet [<Staff: sam-对象>]>
# 八、查询招聘月份是5月的员工
      staff_obj = models.Staff.objects.filter(recruit_time__month=5)
      print(staff_obj)  # <QuerySet [<Staff: linda-对象>, <Staff: frank-对象>, <Staff: july-对象>]>
# 九、查询招聘年份是2020年的员工
      staff_obj = models.Staff.objects.filter(recruit_time__year=2020)
      print(staff_obj)  # <QuerySet [<Staff: rose-对象>, <Staff: tom-对象>, <Staff: Simon-对象>]>

orm创建外键关系

class Staff(models.Model):
    name = models.CharField(max_length=32)
    age = models.IntegerField()
    salary = models.DecimalField(max_digits=8, decimal_places=2)
    recruit_time = models.DateField(auto_now=True)

    def __str__(self):
        return "%s-对象" % self.name


# 图书表
class Book(models.Model):
    book_title = models.CharField(max_length=64, verbose_name='图书名')
    book_price = models.DecimalField(max_digits=6, decimal_places=2, verbose_name='图书价格')
    publish_time = models.DateField(auto_now=True, verbose_name='出版日期')
    publish = models.ForeignKey(to='Press')
    authors = models.ManyToManyField(to='Author')

    def __str__(self):
        return "%s-图书对象" % self.book_title


# 出版社表
class Press(models.Model):
    press_name = models.CharField(max_length=64, verbose_name='出版社名称')
    press_addr = models.CharField(max_length=64, verbose_name='出版社地址')

    def __str__(self):
        return "%s-出版社对象" % self.press_name


# 作者表
class Author(models.Model):
    author_name = models.CharField(max_length=64, verbose_name='作者姓名')
    author_age = models.IntegerField(verbose_name='作者年龄')
    author_details = models.OneToOneField(to='AuthorDetail')

    def __str__(self):
        return "%s-作者对象" % self.author_name


# 作者详情表
class AuthorDetail(models.Model):
    author_addr = models.CharField(max_length=64, verbose_name='作者地址')
    author_phone = models.BigIntegerField(verbose_name='作者联系方式')

    def __str__(self):
        return "%s-作者详情对象" % self.author_addr

外键字段的增删改查

# 一对多、一对一外键字段操作
  增
    models.Book.objects.create(book_title='初中地理', book_price=29, publish_id=1)
    publish_obj = models.Press.objects.filter(pk=3).first()
    models.Book.objects.create(book_title='初中生物', book_price=36, publish=publish_obj)
  改
    res = models.Book.objects.filter(pk=5).update(publish_id=1)
    print(res)
    publish_obj = models.Press.objects.filter(pk=2).first()
    res = models.Book.objects.filter(pk=6).update(publish_id=publish_obj)
    print(res)
 
# 多对多字段操作
  一、第三张关系表创建数据
    book_obj = models.Book.objects.filter(pk=2).first()
    book_obj.authors.add(3, 4)
    book_obj = models.Book.objects.filter(pk=3).first()
    author_obj = models.Author.objects.filter(pk=5).first()
    book_obj.authors.add(author_obj)
	注意:括号内可以放主键值也可以放数据对象,并且都支持多个
  二、第三张关系表修改数据
    book_obj = models.Book.objects.filter(pk=2).first()
    book_obj.authors.set([5])
    注意:括号内必须是一个可迭代对象,元素同样支持主键值或者数据对象
  三、第三张关系表删除数据
    book_obj = models.Book.objects.filter(pk=2).first()
    book_obj.authors.remove(5)
    注意:括号内可以放主键值也可以放数据对象并且都支持多个
  四、第三张关系表清空指定数据
    book_obj = models.Book.objects.filter(pk=3).first()
    book_obj.authors.clear()
    注意:括号内无需传值,直接清空当前表在第三张关系表中的绑定记录

正反向的概念

核心在于当前数据对象是否含有外键字段:有则是正向,没有则是反向

正向

eg:
由书籍查询出版社,外键字段在书籍表中,那么书查出版社就是'正向'
由书籍查询作者,外键字段在书籍表中,那么书查作者就是'正向'
由作者查询作者详情,外键字段在作者表中,那么也是'正向'

反向

eg:
由出版社查询书籍 外键字段不在出版社表 那么出版社查书就是'反向'

多表查询

基于对象的跨表查询

基于对象的跨表查询本质就是子查询即分步操作即可

# 查询初中生物书籍对应的出版社
# book_obj = models.Book.objects.filter(book_title='初中生物').first()
# res = book_obj.publish
# print(res)  # 西南师范大学出版社-出版社对象

# 查询小学英语对应的作者
# book_obj = models.Book.objects.filter(book_title='小学英语').first()
# res = book_obj.authors.all()
# print(res)  # <QuerySet [<Author: david-作者对象>, <Author: 李华-作者对象>]>

# 查询作者david的详情信息
# author_obj = models.Author.objects.filter(author_name='david').first()
# res = author_obj.author_details
# print(res)  # 北京-作者详情对象

# 查询四川大学出版社出版的书籍
# publish_obj = models.Press.objects.filter(press_name='四川大学出版社').first()
# res = publish_obj.book_set.all()
# print(res)  # <QuerySet [<Book: 初中英语-图书对象>, <Book: 初中数学-图书对象>, <Book: 科学世界-图书对象>]>

# 查询朱巍编写的书籍
# author_obj = models.Author.objects.filter(author_name='朱巍').first()
# res = author_obj.book_set.all()
# print(res)  # <QuerySet [<Book: 地理探索-图书对象>, <Book: 初中生物-图书对象>]>

# 查询地址在杭州的作者
# author_detail_obj = models.AuthorDetail.objects.filter(author_addr='杭州').first()
# res = author_detail_obj.author
# print(res)  # 李华-作者对象

基于双下划线的跨表查询

基于双下划线的跨表查询本质就是联表操作

# 查询科学世界书籍对应的出版社名称
# res = models.Press.objects.filter(book__book_title='科学世界')
# print(res)  # <QuerySet [<Press: 四川大学出版社-出版社对象>]>
# res = models.Press.objects.filter(book__book_title='科学世界').values('press_name')
# print(res)  # <QuerySet [{'press_name': '四川大学出版社'}]>

# 查询地理探索对应的作者姓名和年龄
# res = models.Author.objects.filter(book__book_title='地理探索').values('author_name', 'author_age')
# print(res)  # <QuerySet [{'author_name': '朱巍', 'author_age': 32}]>

# 查询作者david的联系方式和地址
# res = models.AuthorDetail.objects.filter(author__author_name='david').values('author_phone', 'author_addr')
# print(res)  # <QuerySet [{'author_phone': 19940405858, 'author_addr': '北京'}]>

# 查询西南师范大学出版社出版的书籍名称和价格
# res = models.Book.objects.filter(publish__press_name='西南师范大学出版社').values('book_title', 'book_price')
# print(res)  # <QuerySet [{'book_title': '小学英语', 'book_price': Decimal('40.00')}, {'book_title': '初中生物', 'book_price': Decimal('36.00')}]>

# 查询王涛编写的书籍名称和日期
# res = models.Book.objects.filter(authors__author_name='王涛').values('book_title', 'publish_time')
# print(res)  # <QuerySet [{'book_title': '科学世界', 'publish_time': datetime.date(2020, 8, 12)}, {'book_title': '初中生物', 'publish_time': datetime.date(2022, 5, 17)}]>

# 查询地址在北京的作者的姓名和年龄
# res = models.Author.objects.filter(author_details__author_addr='北京').values('author_name', 'author_age')
# print(res)  # <QuerySet [{'author_name': 'david', 'author_age': 24}]>

双下线查询扩展

基于双下划线的跨表查询的结果也可以是完整的数据对象

# 查询科学世界书籍对应的出版社名称
# res = models.Press.objects.filter(book__book_title='科学世界').first()
# print(res)  # 四川大学出版社-出版社对象

# 查询地理探索对应的作者姓名和年龄
# res = models.Author.objects.filter(book__book_title='地理探索').values('author_name', 'author_age')
# print(res)  # <QuerySet [{'author_name': '朱巍', 'author_age': 32}, {'author_name': '李华', 'author_age': 26}]>

# 查询作者david的联系方式和地址
# res = models.AuthorDetail.objects.filter(author__author_name='david').values('author_phone', 'author_addr')
# print(res)  # <QuerySet [{'author_phone': 19940405858, 'author_addr': '北京'}]>

# 查询西南师范大学出版社出版的书籍名称和价格
res = models.Book.objects.filter(publish__press_name='西南师范大学出版社').values('book_title', 'book_price')
print(res)  # <QuerySet [{'book_title': '小学英语', 'book_price': Decimal('40.00')}, {'book_title': '初中生物', 'book_price': Decimal('36.00')}]>

# 查询王涛编写的书籍名称和日期
# res = models.Book.objects.filter(authors__author_name='王涛').values('book_title', 'publish_time')
# print(res)  # <QuerySet [{'book_title': '科学世界', 'publish_time': datetime.date(2020, 8, 12)}, {'book_title': '初中生物', 'publish_time': datetime.date(2022, 5, 17)}]>

# 查询地址在北京的作者的姓名和年龄
# res = models.Author.objects.filter(author_details__author_addr='北京').values('author_name', 'author_age')
# print(res)  # <QuerySet [{'author_name': 'david', 'author_age': 24}]>

# 连续跨表操作
# 查询小学英语对应的作者的地址
res = models.AuthorDetail.objects.filter(author__book__book_title='小学英语').values('author_addr')
print(res)  # <QuerySet [{'author_addr': '北京'}, {'author_addr': '杭州'}]>

# 获取多张表里面的字段数据
# 查询初中数学对应的作者的地址和出版社名称
res = models.AuthorDetail.objects.filter(author__book__book_title='初中数学').values('author_addr', 'author__book__publish__press_name')
print(res)  # <QuerySet [{'author_addr': '北京', 'author__book__publish__press_name': '四川大学出版社'}]>

如何查看SQL语句

方式1:句点符加query查看

如果结果集对象是queryset可以点query查看

方式2:配置文件固定配置

只要执行了orm操作都会打印内部SQL语句

LOGGING = {
    'version': 1,
    'disable_existing_loggers': False,
    'handlers': {
        'console': {
            'level': 'DEBUG',
            'class': 'logging.StreamHandler',
        },
    },
    'loggers': {
        'django.db.backends': {
            'handlers': ['console'],
            'propagate': True,
            'level': 'DEBUG',
        },
    }
}

posted @   一梦便是数千载  阅读(30)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?
点击右上角即可分享
微信分享提示