ORM(Object Relation Mapping)
ORM用来把对象模型表示的对象映射到基于SQL的关系模型数据库结构中去。这样,我们在具体的操作实体对象的时候,就不需要再去和复杂的SQL语句打交道,只需简单的操作实体对象的属性和方法根据类创建对象,对象转换成SQL,执行SQL。
在ORM中,类代表的是数据库中的表,类对象代表的是数据库中的表记录,类属性代表的是数据库中的表字段。
如何在pycharm终端中打印出ORM对应的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', }, } }
创建ORM
- 首先在PyCharm中创建一个Django工程,并在创建好之后的终端中输入
python manage.py startapp 文件名
。 - 在创建好之后,在与根目录同名的文件夹中的
settings.py
文件中的INSTALLED_APPS
中添加刚才创建的文件app,格式为:文件名
。 - ORM可以对数据库进行操作,但是不能创建数据库,所以要先创建好数据库
- 在
settings.py
文件中,找到DATABASES
,添加要连接的数据库相应参数
- 然后在刚才创建的文件夹中,找到models.py文件,在其中就可以创建ORM类了。
- 在创建好类之后,在PyCharm终端中,输入如下语句
python manage.py makemigrations
和python manage.py migrate
就可以在相应的数据库中生成相应的表。
在网页上显示结果
参考上一篇文章https://blog.csdn.net/weixin_43265998/article/details/102529915
通过ORM操作数据库
在通过python manage.py startapp 文件名
创建文件夹之后,会有一个views.py文件,在这个文件中我们创建方法,通过函数调用来实现数据库的增删改查。不过首先要把models.py
中的类通过from 文件名.models import *
导过来
-
添加数据
增加数据有两种方式,一种是通过实例化类,一种是通过object方式。- 实例化类
from django.shortcuts import render,redirect,HttpResponse from 文件名.models import * def addbook(request): book = Books(title='linux',price=32,publisher='123',pub_date='2017-12-14') book.save() return HttpResponse('ok')
- 通过
object
属性from django.shortcuts import render,redirect,HttpResponse from 文件名.models import * def addbook(request): # book = Books(title='linux',price=32,publisher='123',pub_date='2017-12-14') # book.save() # create方法返回当前生成的表记录对象 Books.objects.create(title='linux',price=32,publisher='123',pub_date='2017-12-14') # 返回一个Books对象 return HttpResponse('ok')
- 实例化类
-
查询数据
先创建book_list.html文件并编写如下代码:<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>书籍列表</title> <meta name="viewport" content="width=device-width initial-scale=1"> <!-- 最新版本的 Bootstrap 核心 CSS 文件 --> <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@3.3.7/dist/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous"> </head> <body> <h1>书记列表</h1> <div class="container"> <div class="row"> <div class="col-md-8 col-md-offset-2"> <a class="btn btn-primary" href="/add_book/">添加书籍</a> <table class="table table-striped table-hover"> <thead> <tr class="text-center"> <th>编号</th> <th>书籍名称</th> <th>价格</th> <th>出版社</th> <th>出版日期</th> <th>操作</th> </tr> </thead> <tbody> {% for book in book_list %} <tr class="text-center"> <td>{{ forloop.counter }}</td> <td>{{ book.title }}</td> <td>{{ book.price }}</td> <td>{{ book.publisher }}</td> <td>{{ book.pub_date }}</td> <td> <a class="btn btn-success" href="/edit_book/{{ book.id }}">修改</a> </td> <td> <a class="btn btn-danger" href="/del_book/{{ book.id }}">删除</a> </td> </tr> {% endfor %} </tbody> </table> </div> </div> </div> </body> </html>
在urls.py中的
urlpatterns
中添加path('book_list/', views.booklist, name='books'),
。同时在相应的views.py文件中创建如下方法。def booklist(request): book_list = Books.objects.all() return render(request, 'book_list.html', {'book_list': book_list})
查询方法总结:
<1> all(): # 查询所有结果,返回一个QuerySet。 <2> filter(**kwargs): # 它包含了与所给筛选条件相匹配的对象,返回一个QuerySet。 <3> get(**kwargs): # 返回与所给筛选条件相匹配的对象,返回结果有且只有一个,如果符合筛选条件的对象超过一个或者没有都会抛出错误。返回查询到的model对象。 <4> exclude(**kwargs): # 它包含了与所给筛选条件不匹配的对象,返回一个QuerySet。 <5> order_by(*field): # 对查询结果排序,由QuerySet调用,返回一个QuerySet。 <6> reverse(): # 对查询结果反向排序,由QuerySet调用,返回一个QuerySet。 <8> count(): # 返回数据库中匹配查询(QuerySet)的对象数量。由QuerySet调用,返回一个int。 <9> first(): # 返回第一条记录,由QuerySet调用,返回一个model对象。 <10> last(): # 返回最后一条记录由QuerySet调用,返回一个model对象。 <11> exists(): # 如果QuerySet包含数据,就返回True,否则返回False。由QuerySet调用,返回布尔值。 <12> values(*field): # 返回一个ValueQuerySet——一个特殊的QuerySet,运行后得到的并不是一系列model的实例化对象,而是一个可迭代的字典序列。由QuerySet调用,返回一个QuerySet。 <13> values_list(*field): # 它与values()非常相似,它返回的是一个元组序列,values返回的是一个字典序列。由QuerySet调用,返回一个QuerySet。 <14> distinct(): # 从返回结果中剔除重复纪录,通常和values一起使用,单独使用distinct是没有效果的,因为有主键id的存在。由QuerySet调用,返回一个QuerySet。
模糊查询:
Book.objects.filter(price__in=[100,200,300]) Book.objects.filter(price__gt=100) # 大于 gt(greater than) __gte大于等于 Book.objects.filter(price__lt=100) # 小于 lt(less than) __lte小于等于 Book.objects.filter(price__range=[100,200]) Book.objects.filter(title__contains="python") #类似于使用like查询,精准区分大小写 Book.objects.filter(title__icontains="python") # 忽略大小写的like查询 Book.objects.filter(title__startswith="py") # 以py开头,区分大小写 Book.objects.filter(title__istartswith="py") # 以py开头,不区分大小写 Book.objects.filter(pub_date__year=2012,pub_date__month=7) # 查询时间在2017年7月的,如果查不出来,在settings.py中修改USE_TZ = Fslse。
-
删除数据
在urls.py中的from django.urls import path, re_path
,在下面的urlpatterns
中添加re_path('del_book/(\d+)', views.delbook, name='delbook')
。同时在相应的views.py文件中创建如下方法。def delbook(request, del_book_id): Books.objects.filter(id=del_book_id).delete() return redirect(reverse('books'))
-
编辑数据
创建eidt_book.html。<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>编辑书籍</title> <meta name="viewport" content="width=device-width initial-scale=1"> <!-- 最新版本的 Bootstrap 核心 CSS 文件 --> <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@3.3.7/dist/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous"> <style> .container { margin-top: 100px; } </style> </head> <body> {% csrf_token %} <h1>编辑书籍</h1> <div class="container "> <form action="{% url 'editbook' edit_book.id %}" method="post"> {% csrf_token %} <div class="form-group"> <label for="title">Title</label> <input type="text" class="form-control" value="{{ edit_book.title }}" name="title"> </div> <div class="form-group"> <label for="price">价格</label> <input type="text" class="form-control" value="{{ edit_book.price }}" name="price"> </div> <div class="form-group"> <label for="publisher">出版社</label> <input type="text" class="form-control" value="{{edit_book.publisher}}" name="publisher"> </div> <div class="form-group"> <label for="pub_date">出版日期</label> <input type="date" class="form-control" value="{{ edit_book.pub_date|date:'Y-m-d' }}" name="pub_date"> </div> <button type="submit" class="btn btn-warning pull-right">Submit</button> </form> </div> </body> </html>
在urls.py中的
from django.urls import path, re_path
,在下面的urlpatterns
中添加re_path('edit_book/(\d+)', views.editbook, name='editbook'),
。同时在相应的views.py文件中创建如下方法。def editbook(request, edit_book_id): if request.method == 'POST': title = request.POST.get('title') price = request.POST.get('price') publisher = request.POST.get('publisher') pub_date = request.POST.get('pub_date') Books.objects.filter(id=edit_book_id).update(title=title, price=price, publisher=publisher, pub_date=pub_date) return redirect(reverse('books')) else: edit_book = Books.objects.filter(id=edit_book_id) print(edit_book_id) print(edit_book) print(type(edit_book)) # 得到的是<class 'django.db.models.query.QuerySet'> print(edit_book[0]) # print('*****************************') # edit_book1 = Books.objects.get(id=edit_book_id) # print(edit_book_id) # print(edit_book1) # print(type(edit_book1)) # 得到的是<class 'app01.models.Books'> # print(edit_book1) return render(request, 'edit_book.html', {'edit_book': edit_book[0]})
特别的我们可以看到当时用
filter
和get
得到的返回值是不一样的,当使用get
得到的是Books的一个对象,不用使用索引取值,但使用filter
时,就需要使用索引取到第一个值。当通过使用GET
获取url时,会得到url中?
之后的键值对,并通过字典的方式返回,所以我们可以通过request.GET.get('字段')
的方式得到值,以便通过这个索引值,来对数据库进行操作。