高考加油!
带好证件!

Django模型层之单表操作---ORM、增删改、简单查、查询接口、简单图书管理系统

2021-04-02 大聪明 0评论 104 0喜欢

@[TOC]

Django模型层---单表操作

参考:https://www.cnblogs.com/clschao/articles/10427807.html

ORM简介

  • ORM是“对象-关系-映射”的简称。(Object Relational Mapping,简称ORM)(将来会学一个sqlalchemy,是和他很像的,但是django的orm没有独立出来让别人去使用,虽然功能比sqlalchemy更强大,但是别人用不了)
  • 类 --- 表
  • 对象 --- 行
  • 属性 --- 字段
app01下的models.py:
    from django.db import models

    # Create your models here.

    class UserInfo(models.Model):
        id = models.AutoField(primary_key=True)
        # create table userinfo(id int primary key auto_increment, name varchar(16), age int, current_date date);
        name = models.CharField(max_length=16)
        age = models.IntegerField()
        current_date = models.DateField()
    # python manage.py makemigrations
    # python manage.py migrate
# 不连接mysql,默认链接的是sqllite

配置mysql数据库

1. settings.py文件中配置:
    DATABASES = {
        'default': {
            'ENGINE': 'django.db.backends.mysql',
            'HOST': '127.0.0.1',
            'PORT': 3306,
            'NAME': 'orm01',
            'USER': 'root',
            'PASSWORD': '',
        }
    }
2. 项目文件夹下的init文件中,写上下面两句
    import pymysql
    pymysql.install_as_MySQLdb()
3. 执行数据库同步指令
    python manage.py makemigrations
    python manage.py migrate

在settings.py中加上这句话,可以在控制台看到翻译后的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',
        },
    }
}

ORM单表增删改查

    # 创建记录方式1
    student_obj = models.Student(
        name='老王',
        age=19,
    )
    student_obj.save() # 刷到表里
    # 创建记录方式2
    new_obj = models.Student.objects.create(name='小李', age=15) # Student object -- models对象
    print(new_obj.name)
    print(new_obj.age)

    创建方式3
    批量创建
    objs = []
    for i in range(20):
        obj = models.Student(
            name='xiangxi%s' % i,
            age=10 + i,
        )
        objs.append(obj)

    models.Student.objects.bulk_create(objs)

    创建方法4
    update_or_create() 有就更新 没有就创建、
    models.Student.objects.update_or_create(
        name='老王2',
        defaults={
            'age':48,
        }
    )

删除 delete  queryset 和 model 都可以调用
models.Student.objects.get(id=2).delete()  # model对象调用delete方法
models.Student.objects.filter(name='小小').delete()
models.Student.objects.all().delete()  # 删除所有

更新 update() 方法  model对象不能调用更新方法
只能QuerySet调用
models.Student.objects.filter(name='老王').update(age=29)

简单查

简单查询
查询所有
all_obj = models.Student.objects.all()
print(all_obj)  # <QuerySet [<Student: Student object>, <Student: Student object>]>--类似于列表 -- QuerySet集合
for i in all_obj:
    print(i.name)

条件查询  .filter() 返回的也是QuerySet集合,查不到返回一个空集合,不报错
objs = models.Student.objects.filter(id=2)
objs = models.Student.objects.filter(name='老王')
print(objs)

条件查询  get() 返回的是model对象,而且get方法有且必须有1个结果
obj = models.Student.objects.get(id=1)
print(obj)  # 老王
obj = models.Student.objects.get(name='小小')  # 报错1,查询结果多于1个
get() returned more than one Student -- it returned 2!
obj = models.Student.objects.get(name='大大')  # 报错2 没有查询到任何内容
# Student matching query does not exist.
print(obj)

查询接口

<1> all():                  查询所有结果,结果是queryset类型

<2> filter(**kwargs):       它包含了与所给筛选条件相匹配的对象,结果也是queryset类型 Book.objects.filter(title='linux',price=100) #里面的多个条件用逗号分开,并且这几个条件必须都成立,是and的关系,or关系的我们后面再学,直接在这里写是搞不定or的
      models.Student.objects.filter(id=7, name='xiangxi0').update(
            name='小小妹妹',
            age=18,
        )

<3> get(**kwargs):          返回与所给筛选条件相匹配的对象,不是queryset类型,是行记录对象,返回结果有且只有一个,
                            如果符合筛选条件的对象超过一个或者没有都会抛出错误。捕获异常try。  Book.objects.get(id=1)

<4> exclude(**kwargs):      排除的意思,它包含了与所给筛选条件不匹配的对象,没有不等于的操作昂,用这个exclude,返回值是queryset类型 Book.objects.exclude(id=6),返回id不等于6的所有的对象,或者在queryset基础上调用,Book.objects.all().exclude(id=6)
                 
<5> order_by(*field):       queryset类型的数据来调用,对查询结果排序,默认是按照id来升序排列的,返回值还是queryset类型
                  models.Book.objects.all().order_by('price','id') #直接写price,默认是按照price升序排列,按照字段降序排列,就写个负号就行了order_by('-price'),order_by('price','id')是多条件排序,按照price进行升序,price相同的数据,按照id进行升序

<6> reverse():              queryset类型的数据来调用,对查询结果反向排序,返回值还是queryset类型

<7> count():                queryset类型的数据来调用,返回数据库中匹配查询(QuerySet)的对象数量。

<8> first():                queryset类型的数据来调用,返回第一条记录 Book.objects.all()[0] = Book.objects.all().first(),得到的都是model对象,不是queryset

<9> last():                queryset类型的数据来调用,返回最后一条记录

<10> exists():              queryset类型的数据来调用,如果QuerySet包含数据,就返回True,否则返回False
                   空的queryset类型数据也有布尔值True和False,但是一般不用它来判断数据库里面是不是有数据,如果有大量的数据,你用它来判断,那么就需要查询出所有的数据,效率太差了,用count或者exits
                 例:all_books = models.Book.objects.all().exists() #翻译成的sql是SELECT (1) AS `a` FROM `app01_book` LIMIT 1,就是通过limit 1,取一条来看看是不是有数据

<11> values(*field):        用的比较多,queryset类型的数据来调用,返回一个ValueQuerySet——一个特殊的QuerySet,运行后得到的并不是一系列
                            model的实例化对象,而是一个可迭代的字典序列,只要是返回的queryset类型,就可以继续链式调用queryset类型的其他的查找方法,其他方法也是一样的。
<12> values_list(*field):   它与values()非常相似,它返回的是一个元组序列,values返回的是一个字典序列

<13> distinct():            values和values_list得到的queryset类型的数据来调用,从返回结果中剔除重复纪录

基于双下划线的模糊查询  

Book.objects.filter(price__in=[100,200,300]) #price值等于这三个里面的任意一个的对象
Book.objects.filter(price__gt=100)  #大于,大于等于是price__gte=100,别写price>100,这种参数不支持
Book.objects.filter(price__lt=100)
Book.objects.filter(price__range=[100,200])  #sql的between and,大于等于100,小于等于200
Book.objects.filter(title__contains="python")  #title值中包含python的
Book.objects.filter(title__icontains="python") #不区分大小写
Book.objects.filter(title__startswith="py") #以什么开头,istartswith  不区分大小写
Book.objects.filter(pub_date__year=2012)
# 日期查询
# all_books = models.Book.objects.filter(pub_date__year=2012) #找2012年的所有书籍
    # all_books = models.Book.objects.filter(pub_date__year__gt=2012)#找大于2012年的所有书籍
    all_books = models.Book.objects.filter(pub_date__year=2019,pub_date__month=2)#找2019年月份的所有书籍,如果明明有结果,你却查不出结果,是因为mysql数据库的时区和咱们django的时区不同导致的,了解一下就行了,你需要做的就是将django中的settings配置文件里面的USE_TZ = True改为False,就可以查到结果了,以后这个值就改为False,而且就是因为咱们用的mysql数据库才会有这个问题,其他数据库没有这个问题。

作业

  1. 图书管理系统

    功能:对book表的增删改查

    img

    img

django连接mysql的时指定严格模式的配置

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'mxshop',
        'HOST': '127.0.0.1',
        'PORT': '3306',
        'USER': 'root',
        'PASSWORD': '123',
        'OPTIONS': {
            "init_command": "SET default_storage_engine='INNODB'",       #'init_command': "SET sql_mode='STRICT_TRANS_TABLES'",
        }
    }
}
DATABASES['default']['OPTIONS']['init_command'] = "SET sql_mode='STRICT_TRANS_TABLES'"

外部文件使用django的models需要配置django环境

import os

if __name__ == "__main__":
    os.environ.setdefault("DJANGO_SETTINGS_MODULE", "项目名.settings")
    import django
    django.setup()
    from 项目名 import models
    """对表的处理逻辑"""

mysql在配置文件my.ini中设置时区为东八区和设置严格模式:

[mysql]
# 设置mysql客户端默认字符集
default-character-set=utf8
[mysqld]
#设置3306端口
port = 3306
#设置时区为东八区
default-time-zone='+8:00'
#设置为严格模式
sql-mode='STRICT_TRANS_TABLES,NO_ENGINE_SUBSTITUTION'
# 设置mysql的安装目录
basedir=D:\mysql-5.6.50-winx64
# 设置mysql数据库的数据的存放目录
datadir=D:\mysql-5.6.50-winx64\data
# 允许最大连接数
max_connections=200
# 服务端使用的字符集默认为8比特编码的latin1字符集
character-set-server=utf8
# 创建新表时将使用的默认存储引擎
default-storage-engine=INNODB

关闭时区问题

# settings.py
USE_TZ = FALSE

url别名

url(r'^index', views.index, name='bieming')
# 在views.py文件中要引入 反向解析别名工具包
from django.urls import reverse
# 可以改路径 但是别名不需要改,改的话,其他引用别名的地方都需要改
print(reverse('bieming'))  # 解析成 -- /index/
reverse('bieming',args(1,)) # 参数
redirect('bieming')  # 仅限于redirect不用写reverse,可以自动

# 在html文件中用别名
<a href="{%  url 'delete_book'  book.id  %}/" class="btn btn-danger">删除</a>

删除书籍

# form表单里的书籍编号 用 forloop
url(r'^delete_book/(\d+)/', views.delete_book, name='delete_book')
# html
<a href="/delete_book/{{  book.id  }}/" class="btn btn-danger">删除</a>
# 用别名
<a href="{%  url 'delete_book'  book.id  %}/" class="btn btn-danger">删除</a>

编辑页面日期不显示问题

<input type="date" class="form-control" id="date" placehoder="日期" name="" value="{{edit_obj.pub_date|date:'Y-m-d'}}">

发表评论 取消回复

电子邮件地址不会被公开。

请输入正确格式的qq邮箱
请输入以http或https开头的URL,格式如:https://libo_sober.top