zoukankan      html  css  js  c++  java
  • 初学Django基础02 ORM操作

    django的ORM操作

    之前我们知道了models.py这个文件,这个文件是用来读取数据结构的文件,每次操作数据时都走这个模块

    常用字段

      AutoField

        int自增列,必须填入参数 primary_key=True。当model中如果没有自增列,则自动会创建一个列名为id的列。

      IntegerField

        一个整数类型,范围在 -2147483648 to 2147483647。

      CharField

        字符类型,必须提供max_length参数, max_length表示字符长度。

      DateField

        日期字段,日期格式  YYYY-MM-DD,相当于Python中的datetime.date()实例。

      DateTimeField

        日期时间字段,格式 YYYY-MM-DD HH:MM[:ss[.uuuuuu]][TZ],相当于Python中的datetime.datetime()实例。

        SmallIntegerField

        存储范围小

      TextField

        文本字段

    创建表结构

    #models.py

    from django.db import models
    
    
    # Create your models here.
    class Nav(models.Model):
        name = models.CharField(max_length=10, unique=True,
                                verbose_name='导航名称')  # max_length最大个数,unique是否唯一,verbose_name后台列表页,新增,修改页字段的名字
        is_delete = models.SmallIntegerField(default=1, verbose_name='是否被删除')  # default默认值
        create_time = models.DateTimeField(verbose_name='创建时间', auto_now_add=True)  # auto_now_add插入数据的时候,自动取当前时间
        update_time = models.DateTimeField(verbose_name='修改时间', auto_now=True)  # auto_now修改数据的时候,时间会自动变
    
        def __str__(self):
            return self.name  # __str__如果不写打印的是一个对象,加上这段可以打印name值
    
        class Meta:  # 表结构的其他信息
            verbose_name = '导航表'  # 表的中文名
            verbose_name_plural = verbose_name  # 表的中文名
            db_table = 'nav'  # 表名
            # ordering = ['update_time']#查询数据的时候,用来排序的
    
    
    class Article(models.Model):
        title = models.CharField(max_length=20, verbose_name='文章名称',blank=True) # blank表示是否允许为空字符串,不是null值,而是<''>,所有默认都为False
        content = models.TextField(null=True, verbose_name='文章内容')  # null 是否为空,True表示就是数据库的null值,所有默认为False,在TextField字段中, 这个应该一直是False, 设置为True, 数据库会报错
        img = models.ImageField(upload_to='article_img', null=True, verbose_name='文章图片',
                                default='article_img/1.jpg')  # ImageField上传文件,upload_to上传了图片会在setting设置的MEDIA_ROOT路径下自动创建一个article_img的文件夹,注意要使用文件上传必须安装pillow模块
        file = models.FileField(upload_to='file_img',
                                 verbose_name='文件图片')  # FileField与ImageField的唯一不同是ImageField只能上传图片格式的文件,而FileField能上传所有文件
        is_delete = models.SmallIntegerField(default=1, verbose_name='是否被删除')
        nav = models.ForeignKey(Nav, verbose_name='导航id', on_delete=models.DO_NOTHING, db_constraint=False)  # 外键
        create_time = models.DateTimeField(verbose_name='创建时间', auto_now_add=True)
        update_time = models.DateTimeField(verbose_name='修改时间', auto_now=True)
    
        def __str__(self):
            return self.title
    
        class Meta:
            db_table = 'article'
    class Student(models.Model):
        uid = models.AutoField(primary_key=True, verbose_name='学生id')  # AutoField自增长, primary_key主键,每个Model只能有一个主键, 则django会自动添加一个id字段作为主键。
    primary_key=True则必然null=False 并且unique=True
    name = models.CharField(max_length=16, null=False, verbose_name='学生姓名', db_index=True) # db_index创建索引 phone = models.CharField(unique=True, max_length=11, null=False, verbose_name='学生手机') # verbose_name数据库column名称 money = models.DecimalField(default=0, null=True, max_digits=5, decimal_places=2, verbose_name='金额') # DecimalField精度的十进制数字,max_digits允许数字的最大位数(包括小数在内),decimal_places小数最大位数 create_time = models.DateTimeField(verbose_name='创建时间', auto_now_add=True) update_time = models.DateTimeField(verbose_name='修改时间', auto_now=True) status = models.BooleanField(default=1, null=False, verbose_name='学生状态', db_column='状态', editable=False) # editable默认为True,如果为False不在admin后台显示,并且跳过Form校验模型 Email = models.EmailField(null=False) # EmailField邮箱
        sex = models.CharField(default='x', max_length=1,choices=(('x', '男'), ('y', '女')))  # choices在后台编辑或者新增可以变为选择下拉框,其中x表示存入数据库的字段,男表示在后台显示的字段
        def __str__(self):
            return self.name
    
        class Meta:
            db_table = 'student'
            verbose_name = '学生表'
            verbose_name_plural = verbose_name
         indexes = models.Index(fields=['uid','name','phone'],name='student_index') # indexes表示建立表索引,fields索引列,name索引名称
         unique_together = (('name','phone'),'uid') # 建表时建立普通唯一索引或者联合唯一索引
    #多对多关联
    class Book(models.Model):
        nid = models.AutoField(primary_key=True)
        title = models.CharField(max_length=32)
        price = models.CharField(max_length=32)
        pub_date = models.DateField()  # 如果是datafield默认插入格式为2019-01-01
        publish = models.ForeignKey(to='Publish', on_delete=models.CASCADE, to_field='nid',null=True)  # to,关联的表名类
        # to_field关联表的字段,默认为不填主键,
        # on_delete级联删除
        authors = models.ManyToManyField(to='Author')  # 建立多对多关系表,Book和Author的关联表,由django自动创建
        def __str__(self):
            return self.title
    
    
    class Publish(models.Model):
        nid = models.AutoField(primary_key=True)
        name = models.CharField(max_length=32)
        email = models.CharField(max_length=32)
    
        def __str__(self):
            return self.name
        class Meta:  # 表结构的其他信息
            verbose_name = '出版行表'  # 表的中文名
            verbose_name_plural = verbose_name  # 表的中文名
            db_table = 'publish'  # 表名
    
    #一对一关联
    class Author(models.Model):
        nid = models.AutoField(primary_key=True)
        name= models.CharField(max_length=32)
        age = models.IntegerField()
        email = models.CharField(max_length=32)
        #ad = models.ForeignKey('AuthorDetail',on_delete=models.CASCADE,unique=True)#建立外键关联,之后加入unique=True建立唯一约束,这样就是一对一表的关系了
        ad = models.OneToOneField(to='AuthorDetail',on_delete=models.CASCADE)#django用了更加便捷的做法,这和上面的一样
    
    class AuthorDetail(models.Model):
        addr = models.CharField(max_length=32)
        tel = models.IntegerField()

    运行到数据库中

      #生成迁移文件

    python manage.py makemigrations
      #查看迁移文件是否同步到数据库,[x]表示都同步了
    python manage.py showmigrations user
      #同步到数据库中
    python manage.py migrate

       #通过拿到的数据库,自动生成models.py文件

    python manage.py inspectdb > models_test1.py   #指定所有表
    python manage.py inspectdb user > models_test2.py #指定user表生成

    djangoORM的增删改查

    # 这三句表示告诉django我要操作哪个数据库
    import django, os
    
    os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'dj_test.settings')  # 设置django的配置文件
    django.setup()  # 配置并检查
    
    from user import models  # 找到对应的表结构文件
    
    # 新增
    models.Nav.objects.create(name='我的日记')
    
    # 这样也可以新增
    nav_obj = models.Nav(name='我的心情', is_delete=1)
    nav_obj.save()
    
    # 查询
    # get方法查询的话,必须得保证这个数据查出来只有1条,才可以
    result = models.Nav.objects.get(is_delete=1)
    print(result.name)
    
    # 加了filter搜索出来的结果就有可能是多条
    result0 = models.Nav.objects.filter(is_delete=1, name='我的心情')  # and
    result1 = models.Nav.objects.filter(name__contains='我的')  # 模糊查询
    result1_1 = models.Nav.objects.filter(create_time__endswith='84')  # 查询匹配结尾字符
    result1_2 = models.Nav.objects.filter(create_time__startswith='2019')  # 查询匹配开头字符
    result1_3 = models.Nav.objects.filter(create_time__isnull=True)  # 查询是否为空的
    result2 = models.Nav.objects.filter(id__gt=0)  # 大于0
    result3 = models.Nav.objects.filter(id__gte=1)  # 大于等于1
    result4 = models.Nav.objects.filter(id__lt=2)  # 小于2
    result5 = models.Nav.objects.filter(id__range=[1, 5])  # 一个范围之间
    result6 = models.Nav.objects.filter(id__in=[1, 2, 3, 5, 6])  # in
    result7 = models.Nav.objects.exclude(id=1)  # 排除,除了id为1的
    result8 = models.Nav.objects.filter(pk=1) #pk,意思为primary key主键的缩写,这个关键字默认获取主键信息
    from django.db.models import Q result8 = models.Nav.objects.filter(Q(name__contains='6') | Q(name__contains='3')) # result9 = models.Nav.objects.all().filter(name__contains='6') # 获取表里面所有的数据 result10 = models.Nav.objects.all().filter(name__contains='6').count() # count可以获取个数 result11 = models.Nav.objects.all().filter(name__contains='6').values() # values返回字典显示
    result11_1 = models.Nav.objects.all().filter(name__contains='6').values('name','is_delete')
    # values可以指定返回的字段名称从而指定返回的字段
    result12 = models.Nav.objects.raw('select * from nav') # 执行原生sql # 修改 # 此方法修改就是对一个值重新赋值的方式 n = models.Nav.objects.get(id=1) # parimy key n.name = 'wo的相册2' n.is_delete = 1 n.save() models.Nav.objects.all().update(is_delete=0) # 更新表里面所有数据 models.Nav.objects.filter(name__contains='我的').update(is_delete=1) # 根据条件 # 删除 models.Nav.objects.all().delete() # 删除表里面所有数据 models.Nav.objects.filter(id__lt=3).delete() # 根据条件删除 n = models.Nav.objects.get(id=3) # parimy key单个删除 n.delete() # 反向查询 关联字段不在查询的表中,而#向查询是关联字段在查询的表中 art_obj = models.Nav.objects.get(name='我的日记3') print(art_obj.article_set.filter()) # 外键反向查询,表名加_set,注意当一对一关联时不需要加_set # nav_obj.article_set.add(art_obj)#添加 # nav_obj.article_set.remove(art_obj)#删除 # nav_obj.article_set.clear()#清空
    # nav_obj.article_set.set(art_obj)#修改
    #join跨表操作
    #注意正向查询按字段,反向查询按表名
    ret01 = Book.objects.filter(title='python').values('publish__name')#正向跨表查询,字段以publish表的name字段做显示
    ret02 = Publish.objects.filter(book__title='python').values('name')#反向跨表查询,表以publish表关联的book表,查询name字段做显示
    #如果拼接n张表,这种称为连续跨表,确保表之间都连接关联关系,按照基表与要查询的数据之间的关联关系连续跨域最后找到该字段,中间按照'__'作为连接
    #如:
    #Publish.objects.filter(book__title__nav).value('xx')
    
    
    #聚合
    from django.db.models import Avg,Max,Count,Min,Sum #要用哪个输入哪个
    ret=  Book.objects.all().aggregate(Avg('price'))#aggregate表示使用聚合函数,{'price__avg': 222.0}
    ret=  Book.objects.all().aggregate(aaa=Avg('price'))#{'aaa': 222.0}自定义键名
    ret=  Book.objects.all().aggregate(Count('nid'))

    执行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',
            },
        }
    }

    执行sql语句日志文件打印配置

    LOGGING = {
        'version': 1,
        'disable_existing_loggers': False,
        'formatters': {
            'verbose': {
                'format': '%(levelname)s %(asctime)s %(module)s %(process)d %(thread)d %(message)s'
            },
            'simple': {
                'format': '%(levelname)s %(asctime)s %(module)s %(message)s'
            },
        },
        'handlers': {
            'sql': {
                'level': 'DEBUG',
                'class': 'logging.FileHandler',
                'filename': os.path.join(BASE_DIR, "sql_info.log"),
                'formatter': 'simple'
            },
            'console': {
                'level': 'DEBUG',
                'class': 'logging.StreamHandler',
            }
        },
        'loggers': {
            'django.db.backends': {
                'handlers': ['sql', 'console'],
                'propagate': True,
                'level': 'DEBUG',
            },
        }
    }

    版权声明:本文原创发表于 博客园,作者为 RainBol 本文欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则视为侵权。

  • 相关阅读:
    python自定义编写有关用户登录注册程序代码
    项目经理多年的经验之谈
    Linux虚拟机克隆后,启动系统发现网卡无法启动
    mysql出现服务器异常后,重启服务器后无法开启数据库处理方法
    计算机毕业四年,我都做了什么?
    个人Blog(采用Django+uwsgi+nginx)里面包含很多技术文章
    Delphi to C# Equivalancesdelphi和C#类似的地方
    Javascript浏览器关于scrollLeft,scrollTop的兼容性
    Mozilla Firefox15怎么样才能把标签页弄到下面去,就和360的一样,Mozilla Firefox15没有取消标签置顶这个选项……
    Delphi过程函数传递参数的几种方式
  • 原文地址:https://www.cnblogs.com/RainBol/p/11718456.html
Copyright © 2011-2022 走看看