django系列5.1--ORM对数据库的操做

Django--—ORM数据库操做(图书管理系统基本实例)html

一.基本知识

MVC模式(Model–view–controller)是软件工程中的一种软件架构模式,把软件系统分为三个基本部分:模型(Model)、视图(View)和控制器(Controller)。python

ORM:对象关系映射(Object Relational Mapping,简称ORM,或O/RM,或O/R mapping),是一种程序技术,用于实现面向对象编程语言里不一样类型系统的数据之间的转换 。 从效果上说,它实际上是建立了一个可在编程语言里使用的-–“虚拟对象数据库”。mysql

FBV (function base views)就是在视图里使用函数处理请求。linux

CBV(class base views) 就是在视图里使用类处理请求。git

<br/>sql

二.为项目添加新app

注意新添加app时应在配置文件中的INSTALLED_APPS中写入咱们建立的app名称数据库

INSTALLED_APPS = [
    'django.contrib.admin',  #这是django给你提供的一些特殊功能的配置(应用,只是我们看不到),也在应用这里给配置的,这些功能若是你注销了,那么咱们执行同步数据库指令以后,就不会生成那些django自带的表了。由于执行数据库同步语句的时候,django会找这里面全部的应用,找到他们的models来建立表
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    "book"  #直接写app的名字也行,写'app01.apps.App01Config'也行
]

<br/>django

三.建立与数据库的链接

1.此时首先应创建一个mysql数据库,这里我建立的数据库名为orm<br/>编程

2.settings.py文件中配置数据库链接,(建立项目时有默认的语句,找到DATABASES后修改补全便可)session

# Database
# https://docs.djangoproject.com/en/1.11/ref/settings/#databases

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',  # 链接的数据库类型
        'NAME': 'orm',  # 数据库名称
        'USER':'root',  # 用户名
        'PASSWORD':'123',
        'HOST':'127.0.0.1',
        'PORT':3306
        # 'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),  # 建立项目时默认用的数据库类型
    }
}

sqlite数据库下的db.sqlite3则是项目自动建立 USER和PASSWORD分别是数据库的用户名和密码。设置完后,再启动咱们的Django项目前,咱们须要激活咱们的mysql。而后,启动项目,会报错:no module named MySQLdb 。这是由于django默认你导入的驱动是MySQLdb,但是MySQLdb 对于py3有很大问题,因此咱们须要的驱动是PyMySQL 因此,咱们只须要找到项目名文件下的__init__.py,在里面写入:

<br/>

3.在项目app中的__init__.py 输入下面代码

import pymysql

pymysql.install_as_MySQLdb()

<br/>

4.建立数据库表.先建立模式,项目目录下的models.py

from django.db import models

# Create your models here.
class Book(models.Model):
    id = models.AutoField(primary_key=True)
    title = models.CharField(max_length=32)
    pub_date = models.DateField()
    price = models.DecimalField(max_digits=8,decimal_places=2)
    publish = models.CharField(max_length=20)

    def __str__(self):  # 这里用来之后对数据库操做时在控制台输出titile名称
        return self.title

<br/>

5.须要在terminal中输入两行命令

python3 manage.py makemigrations   # 建立脚本
python3 manage.py migrate   # 迁移

<br/>

6.查看执行的sql语句

在settings.py文件中加入

查看数据库执行代码
LOGGING = {
    'version': 1,
    'disable_existing_loggers': False,
    'handlers': {
        'console':{
            'level':'DEBUG',
            'class':'logging.StreamHandler',
        },
    },
    'loggers': {
        'django.db.backends': {
            'handlers': ['console'],
            'propagate': True,
            'level':'DEBUG',
        },
    }
}

<br/>

四.单表操做

在views.py中添加对数据库的操做语句

#在逻辑代码中导入你要操做的表
from app import models

def add_book(request):
    '''
    添加表记录
    :param request: http请求信息
    :return:
    '''
    models.Book(title='人间失格',price=12,pub_date='2012-12-12',publish='文学出版社')

1.添加表记录

方式1:实例化对象就是一条表记录

from app import models


obj = models.Book(title='复活',price=12,pub_date='2012-12-12',publish='小出版社')
obj.save()

方式2:(咱们通常使用方式二添加)

models.Book.objects.create(title='复活',price=12,pub_date='2012-12-12',publish='小出版社')

<br/>

2.查询表记录

查询全部的记录:

obj = models.Book.objects.all()

使用values的结果:

obj = models.Book.objects.all().values()
# <QuerySet [{'id': 1, 'title': '雪国列车2', 'pub_date': datetime.date(2012, 12, 1),

<br/>

经常使用的查询API:

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

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

<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类型的数据来调用,从返回结果中剔除重复纪录

<br/>

双下划线的单表查询

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)  # 日期查询,年份为2012的数据

<br/>

关于value的用法

all_books = models.Book.objects.all().values('id','title')
print(all_books) 
#<QuerySet [{'title': 'linux', 'id': 6}, {'title': '你好', 'id': 7}, {'title': 'linux', 'id': 8}, {'title': 'xxx', 'id': 9}, {'title': 'gogogo', 'id': 10}]>

    '''
        values作的事情:
        ret = [] #queryset类型
        for obj in Book.objects.all():
            temp = {  #元素是字典类型
                'id':obj.id,
                'title':obj.title
            }
            ret.append(temp)

    '''

</br>

关于时间问题:日期查询

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数据库才会有这个问题,其余数据库没有这个问题。

当查询日期出现问题时:

将settings.py中最下面的USE_TZ = False改成True

USE_TZ = True

不是跨时区的应用,不须要考虑时区问题,就将这个值改成False,mysql是对时区不敏感,django往mysql里面出数据的时候,若是这里的值为True,那么将让mysql强制使用UTC时间,那么咱们存储进入的时间,当你查询的时候,你就会发现,时间晚了8小时,也就是说你存时间的时候被改成了UTC时间,本地是东八区,比UTC时间多8小时

<br/>

3.修改表记录

update只能是QuerySet类型才能调用,model对象不能直接调用更新方法,因此使用get方法获取对象的时候是不能使用update方法的

Book.objects.filter(title__startswith="复活").update(price=12)

注意:

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

type='date'的input标签,value的值必须是'Y-m-d'的格式,这个标签才能认识并被赋值,因此,要经过date过滤给它改变格式。

<br/>

4.删除表记录

删除方法.delete()的调用者能够是一个model对象,也能够是一个queryset集合.它运行时当即删除对象而不返回任何值,也能够一次删除多个对象.每一个queryset都有一个delete()方法

models.Book.objects.filter(title='复活').delete()  # 删除标题为复活的Book对象

任何状况下,QuerySet中的delete()方法都只使用一条SQL语句一次性删除全部对象,而并非分别删除诶个对象,若是想使用model中自定义的delete()方法,就要自行调用每一个对象的delete()方法(例如,遍历 QuerySet,在每一个对象上调用 delete()方法),而不是使用 QuerySet 中的 delete()方法。

在Django删除对象时,会模仿SQL约束 ON DELETE CASCDE的行为(删除一个对象时也会删除与它相关联的外键对象)

b = Blog.objects.get(pk=1)
# This will delete the Blog and all of its Entry objects.
b.delete()

delete() 方法是 QuerySet 上的方法,但并不适用于 Manager 自己。这是一种保护机制,是为了不意外地调用 Entry.objects.delete() 方法致使 全部的 记录被误删除。若是你确认要删除全部的对象,那么你必须显式地调用:

Entry.objects.all().delete()
相关文章
相关标签/搜索