Django学习之模型层

Stella981
• 阅读 705

模型层

查看orm内部sql语句的方法的方法

1.如果是queryset对象,那么可以点query直接查看该queryset的内部sql语句

2.在Django项目的配置文件中,配置一下参数即可实现所有的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',
        },
    }
}

models.py

from django.db import models

# Create your models here.
class Book(models.Model):
    title = models.CharField(max_length=255)
    price = models.DecimalField(max_digits=8,decimal_places=2)
    publish_date = models.DateField(auto_now_add=True)

    # 库存数 后加的,需要手动传值
    kucun = models.IntegerField(null=True)
    # 卖出数 后加的,需要手动传值
    maichu = models.IntegerField(null=True)

    publish = models.ForeignKey(to='Publish')  # 默认是跟publish的主键字段做的一对多外键关联
    authors = models.ManyToManyField(to='Author')
    # 虚拟字段      1.自动创建第三张表    2.帮助orm跨表查询

    def __str__(self):
        return self.title

class Publish(models.Model):
    name = models.CharField(max_length=32)
    addr = models.CharField(max_length=32)
    # email = models.EmailField()  # 就是varchar(254)

    def __str__(self):
        return self.name

class Author(models.Model):
    name = models.CharField(max_length=32)
    age = models.IntegerField()
    author_detail = models.OneToOneField(to='AuthorDetail')

    def __str__(self):
        return self.name
class AuthorDetail(models.Model):
    phone = models.BigIntegerField()
    addr = models.CharField(max_length=64)
    """
    models.py中的模型类__str__方法 必须返回一个字符串形式数据!!!
    
    """
    def __str__(self):
        return self.addr

基于models.py中表的查询方法(补充Q的高级用法末尾)

from django.test import TestCase

# Create your tests here.
import os


if __name__ == "__main__":
    os.environ.setdefault("DJANGO_SETTINGS_MODULE", "day55.settings")
    import django
    django.setup()
    """在下面就可以写针对某一个py文件的测试代码"""
    from app01 import models
    # 一对多的字段的增删改查
    # 增
    # publish_id传数字
    # models.Book.objects.create(title='三国演义',price=189.99,publish_id=1)
    #  publish直接传出版社对象
    # publish_obj = models.Publish.objects.filter(pk=2).first()
    # models.Book.objects.create(title='红楼梦',price=999.99,publish=publish_obj)

    # 改
    # 传数字的
    # models.Book.objects.filter(pk=1).update(publish_id=3)
    # 传对象的
    # publish_obj = models.Publish.objects.filter(pk=2).first()
    # models.Book.objects.filter(pk=1).update(publish=publish_obj)

    # 查

    # 删
    # models.Publish.objects.filter(pk=2).delete()  # 默认都是级联更新 级联删除


    # 多对多字段的增删改查
    # 增
    # 要给主键为1的书籍添加两个作者
    # book_obj = models.Book.objects.filter(pk=1).first()
    # print(book_obj.authors)  # 对象点击多对多虚拟字段 会直接跨到多对多的第三张表
    # book_obj.authors.add(1)
    # book_obj.authors.add(2,3)

    # author_obj = models.Author.objects.filter(pk=1).first()
    # author_obj1 = models.Author.objects.filter(pk=2).first()
    # author_obj2 = models.Author.objects.filter(pk=3).first()
    # book_obj.authors.add(author_obj)
    # book_obj.authors.add(author_obj1,author_obj2)
    """
    add()
    是给书籍添加作者  括号内既可以传数字也可以传对象
    并且支持一次性传多个  逗号隔开即可
    """

    # 改
    # 将主键为1的书籍对象 作者修改为2,3
    # book_obj = models.Book.objects.filter(pk=1).first()
    # book_obj.authors.set([2,])
    # book_obj.authors.set([2,3])

    # author_obj = models.Author.objects.filter(pk=1).first()
    # author_obj1 = models.Author.objects.filter(pk=2).first()
    # author_obj2 = models.Author.objects.filter(pk=3).first()
    # book_obj.authors.set([author_obj,])
    # book_obj.authors.set([author_obj, author_obj1, author_obj2])
    """
    set()括号内 需要传一个可迭代对象 
    可迭代对象中 可以是多个数字组合
    也可以是多个对象组合
    但是不要混着用!!!
    """

    # 删
    # book_obj = models.Book.objects.filter(pk=1).first()
    # # book_obj.authors.remove(3)
    # book_obj.authors.remove(1,2)
    # author_obj = models.Author.objects.filter(pk=1).first()
    # author_obj1 = models.Author.objects.filter(pk=2).first()
    # author_obj2 = models.Author.objects.filter(pk=3).first()
    # book_obj.authors.remove(author_obj)
    # book_obj.authors.remove(author_obj1,author_obj2)
    """
    remove()括号内既可以传数字 也可以传对象 
    并且支持传对个 逗号隔开即可
    """

    # 将某本书跟作者的关系全部清空
    # book_obj = models.Book.objects.filter(pk=1).first()
    # book_obj.authors.clear()  # 清空当前书籍与作者的所有关系

    """
    add()
    set()
    remove()
    上面三个都支持传数字 或者对象 并且可以传多个 但是set需要传可迭代对象
    
    clear()
    clear括号内不需要传任何参数
    """

    # 跨表查询(******)
    """
    正向与反向的概念
    
    # 一对一
    # 正向:author---关联字段在author表里--->authordetail        按字段
    # 反向:authordetail---关联字段在author表里--->author        按表名小写
    
      
    # 一对多
    # 正向:book---关联字段在book表里--->publish        按字段
    # 反向:publish---关联字段在book表里--->book        按表名小写_set.all() 因为一个出版社对应着多个图书
    
    # 多对多
    # 正向:book---关联字段在book表里--->author        按字段
    # 反向:author---关联字段在book表里--->book        按表名小写_set.all() 因为一个作者对应着多个图书
    
    
    正向查询按外键字段
    反向查询按表名小写
    """
    """基于对象的跨表查询(子查询:将一张表的查询结果当做另外一个查询语句的条件)"""
    """
    强调:在书写orm语句的时候 跟写sql语句一样 
    不要尝试着 一次性写完  应该做到写一点看一点再一点
    """
    # 1.查询书籍id是1 的出版社名称
    # book_obj = models.Book.objects.filter(pk=1).first()
    # print(book_obj.publish.name)
    # print(book_obj.publish.addr)

    # 2.查询书籍id是2 的作者姓名
    # book_obj = models.Book.objects.filter(pk=2).first()
    # print(book_obj.authors)  # app01.Author.None
    # print(book_obj.authors.all())
    # res = book_obj.authors.all()
    # for r in res:
    #     print(r.name)

    # 3.查询作者是jason的家庭住址
    # author_obj = models.Author.objects.filter(name='jason').first()
    # print(author_obj.author_detail.addr)


    # 4.查询出版社是东方出版社出版的书籍
    # publish_obj = models.Publish.objects.filter(name='东方出版社').first()
    # # print(publish_obj.book_set)  # app01.Book.None
    # print(publish_obj.book_set.all())

    # 5.查询作者是jason的写过的所有的书籍
    # author_obj = models.Author.objects.filter(name='jason').first()
    # print(author_obj.book_set)  # app01.Book.None
    # print(author_obj.book_set.all())

    # 6.查询电话号码是130的作者姓名
    # author_detail_obj = models.AuthorDetail.objects.filter(phone=130).first()
    # print(author_detail_obj.author.name)
    # print(author_detail_obj.author.age)
    """
    当你反向查询的结果是多个的时候 就需要加_set
    否则直接表明小写即可
    """

    # 7.查询书籍id为1 的作者的电话号码
    # book_obj = models.Book.objects.filter(pk=1).first()
    # author_list = book_obj.authors.all()
    # for author_obj in author_list:
    #     print(author_obj.author_detail.phone)

    """基于双下划綫的跨表查询(连表操作)
        left join
        inner join
        right join
        union
    """
    # 正向
    # 1.查询jason作者的手机号
    # res = models.Author.objects.filter(name='jason').values('author_detail__phone','author_detail__addr')
    # print(res)

    # res1 = models.AuthorDetail.objects.filter(author__name='jason').values('phone')
    # print(res1)


    # 查询jason这个作者的年龄和手机号
    # 正向
    # res = models.Author.objects.filter(name='jason').values('age','author_detail__phone')
    # print(res)
    # 反向
    # res1 = models.AuthorDetail.objects.filter(author__name='jason').values('phone','author__age')
    # print(res1)


    # 查询手机号是130的作者年龄
    # 正向
    # res = models.AuthorDetail.objects.filter(phone=130).values('author__age')
    # print(res)
    # # 反向
    # res1 = models.Author.objects.filter(author_detail__phone=130).values('age')
    # print(res1)

    # 查询书籍id是1 的作者的电话号码
    # res = models.Book.objects.filter(pk=1).values('authors__author_detail__phone')
    # res1 = models.Book.objects.filter(pk=1).values('外键字段1__外键字段2__外键字段3__普通字段')
    # print(res)
    """只要表里面有外键字段 你就可以无限制跨多张表"""

    # 1.查询出版社为北方出版社的所有图书的名字和价格
    # res = models.Publish.objects.filter(name='北方出版社').values('book__title','book__price')
    # print(res)

    # 2.查询北方出版社出版的价格大于19的书
    # res = models.Book.objects.filter(price__gt=19,publish__name='北方出版社').values('title','publish__name')
    # print(res)


    # 聚合查询(aggregate)
    # 1.统计所有书的总价格
    # from django.db.models import Max,Min,Count,Avg,Sum
    #
    # # res = models.Book.objects.aggregate(Sum('price'))
    # res1 = models.Book.objects.aggregate(Avg('price'))
    # res2 = models.Book.objects.aggregate(Count('price'))
    # res3 = models.Book.objects.aggregate(Max('price'))
    # res4 = models.Book.objects.aggregate(Min('price'))
    # res5 = models.Book.objects.aggregate(Max('price'),Min('price'),Count('pk'),Avg('price'),Sum('price'))
    # print(res5)
    # print(res)
    # print(res1)
    # print(res2)


    # 分组查询
    # 统计每一本书的作者个数
    from django.db.models import Max, Min, Count, Avg, Sum
    # res = models.Book.objects.annotate(author_num = Count('authors')).values('author_num','title')
    # print(res)

    # 统计出每个出版社卖的最便宜的书的价格
    # res = models.Publish.objects.annotate(mmp = Min('book__price')).values('name','mmp')
    # print(res)

    # 统计不止一个作者的图书
    # res = models.Book.objects.annotate(author_num=Count('authors')).filter(author_num__gt=1)
    # print(res)

    """
    只要是queryset对象 就可以无限制的调用queryset对象的方法!!!
    最最常用的就是对一个已经filter过滤完的数据 再进行更细化的筛选
    
    """

    # 查询各个作者出的书的总价格
    # res = models.Author.objects.annotate(sp=Sum('book__price')).values('name','sp')
    # print(res)


    #F查询的本质就是从数据库中获取某个字段的值
    # 查询库存数大于卖出数的书籍
    """之前查询等号后面的条件都是我们认为输入的
        现在变成了需要从数据库中获取数据放在等号后面
    """
    from django.db.models import F
    # res = models.Book.objects.filter(kucun__gt=F('maichu'))
    # print(res)


    # 将书籍库存数全部增加1000
    # models.Book.objects.update(kucun=F('kucun')+1000)

    # 把所有书名后面加上'新款'

    # from django.db.models.functions import Concat
    # from django.db.models import Value
    #
    # ret3 = models.Book.objects.update(title=Concat(F('title'), Value('新款')))
    # models.Book.objects.update(title = F('title')+'新款')  # 不能这么写


    # Q查询
    from django.db.models import Q
    # 查询书籍名称是三国演义或者价格是444.44
    # res = models.Book.objects.filter(title='三国演义',price=444.44)  # filter只支持and关系
    # res1 = models.Book.objects.filter(Q(title='三国演义'),Q(price=444))  # 如果用逗号 那么还是and关系
    # res2 = models.Book.objects.filter(Q(title='三国演义')|Q(price=444))
    # res3 = models.Book.objects.filter(~Q(title='三国演义')|Q(price=444))
    # print(res2)


    # Q高级用法
    q = Q()
    q.connector = 'or'  # 修改查询条件的关系   默认是and
    q.children.append(('title__contains','三国演义'))  # 往列表中添加筛选条件
    q.children.append(('price__gt',444))  # 往列表中添加筛选条件
    res = models.Book.objects.filter(q)  # filter支持你直接传q对象  但是默认还是and关系
    print(res)

自定义char字段

    class MyCharField(models.Field):
        def __init__(self,max_length,*args,**kwargs)
            self.max_length = max_length
            super().__init__(max_length=max_length,*args,**kwargs)
        
        def db_type(self,connection):
            return 'char(%s)'%self.max_length
    
    class User(models.Model):
        username = MyCharField(max_length=32)
点赞
收藏
评论区
推荐文章
blmius blmius
3年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
皕杰报表之UUID
​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为
待兔 待兔
4个月前
手写Java HashMap源码
HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22
Jacquelyn38 Jacquelyn38
3年前
2020年前端实用代码段,为你的工作保驾护航
有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )
Stella981 Stella981
3年前
Python3:sqlalchemy对mysql数据库操作,非sql语句
Python3:sqlalchemy对mysql数据库操作,非sql语句python3authorlizmdatetime2018020110:00:00coding:utf8'''
Wesley13 Wesley13
3年前
mysql设置时区
mysql设置时区mysql\_query("SETtime\_zone'8:00'")ordie('时区设置失败,请联系管理员!');中国在东8区所以加8方法二:selectcount(user\_id)asdevice,CONVERT\_TZ(FROM\_UNIXTIME(reg\_time),'08:00','0
Stella981 Stella981
3年前
Django中Admin中的一些参数配置
设置在列表中显示的字段,id为django模型默认的主键list_display('id','name','sex','profession','email','qq','phone','status','create_time')设置在列表可编辑字段list_editable
Wesley13 Wesley13
3年前
MySQL部分从库上面因为大量的临时表tmp_table造成慢查询
背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_
为什么mysql不推荐使用雪花ID作为主键
作者:毛辰飞背景在mysql中设计表的时候,mysql官方推荐不要使用uuid或者不连续不重复的雪花id(long形且唯一),而是推荐连续自增的主键id,官方的推荐是auto_increment,那么为什么不建议采用uuid,使用uuid究
Python进阶者 Python进阶者
10个月前
Excel中这日期老是出来00:00:00,怎么用Pandas把这个去除
大家好,我是皮皮。一、前言前几天在Python白银交流群【上海新年人】问了一个Pandas数据筛选的问题。问题如下:这日期老是出来00:00:00,怎么把这个去除。二、实现过程后来【论草莓如何成为冻干莓】给了一个思路和代码如下:pd.toexcel之前把这