MVC或者MVC框架中包括一个重要的部分,就是ORM,它实现了数据模型与数据库的解耦,即数据模型的设计不需要依赖于特定的数据库,通过简单的配置就可以轻松更换数据库。ORM是“对象-关系-映射”的简称。
sql中的表
# 创建表 create TABLE employee( id INT PRIMARY KEY auto_increment, name varchar(20), gender BIT default 1, birthday DATA, department VARCHAR(20), salary DECIMAL(8,2) unsigned,) ); # 添加一条表记录: INSERT employee(name, gender, birthday, salary, department) VALUES ('alex', '1', '1985-12-12', 8000, '保洁部'); # 查询一条表记录: SELECT * FROM employee WHERE age=24; # 更新一条表记录: UPDATE employee SET birthday='1989-10-24' WHERE id=1; # 删除一条表记录: DELETE FROM employee WHERE name='alex'
而对应的Python的类对象
class Employee(models.Model): id=models.AutoField(primary_key=True) name=models.CharField(max_length=32) gender=models.BooleanField() birthday=models.DateField() department=models.CharField(max_length=32) salary=models.DecimalField(max_digits=8,decimal_places=2) #添加一条表记录: emp=Employee(name='alex', gender=True, birthday='1985-12-12',epartment='保洁部') emp.save() # 查询一条表记录 Employee.objects.filter(age=24) # 更新一条表记录 Emplyoee.objects.filter(id=1).update(birthday='1989-10-24') # 删除一条表记录 Emplypee.objects.filter(name='alex').delete()
1.生成表模型
在该应用的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, unique=True) pub_date = models.DateField() price = models.DecimalField(max_digits=8, decimal_places=2) # max number = 999999.99 publish = models.CharField(max_length=32)
将模型转为mysql数据库中的表,需要在settings中配置:
DATABASES = { 'default': { 'ENGINE': 'django.db.backends.mysql', 'NAME':'bms', # 要连接的数据库,连接前需要创建好 'USER':'root', # 连接数据库的用户名 'PASSWORD':'', # 连接数据库的密码 'HOST':'127.0.0.1', # 连接主机,默认本级 'PORT':3306 # 端口 默认3306 } }
然后我们需要找到总项目包下的__init__.py文件,写入
import pymysql pymysql.install_as_MySQLdb()
最后通过两条数据库迁移命令即可在指定的数据库中创建表 :
>>> python manage.py makemigrations
>>> python manage.py migrate
注意:
确保配置文件中的INSTALLED_APPS中写入我们创建的app名称
INSTALLED_APPS = [ 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', "book" ] # book是应用名
如果你的Django版本是1.0而且Python版本高于3.4,可能会报错如下:
django.core.exceptions.ImproperlyConfigured: mysqlclient 1.3.3 or newer is required; you have 0.7.11.None
需要修改:
通过查找路径C:\Programs\Python\Python36-32\Lib\site-packages\Django-2.0-py3.6.egg\django\db\backends\mysql\base.py 这个路径里的文件把下面两行代码注释掉就ok了。(这个路径并不是固定的,只要找到Python\django里的mysql文件)
if version < (1, 3, 3): raise ImproperlyConfigured("mysqlclient 1.3.3 or newer is required; you have %s" % Database.__version__)
如果你还想要在屏幕上打印转换过程中的sql,需要在settings中进行如下配置:
LOGGING = { 'version': 1, 'disable_existing_loggers': False, 'handlers': { 'console':{ 'level':'DEBUG', 'class':'logging.StreamHandler', }, }, 'loggers': { 'django.db.backends': { 'handlers': ['console'], 'propagate': True, 'level':'DEBUG', }, } }
2.增删改查
添加表记录
方法1:
# create方法的返回值book_obj就是插入book表中的python葵花宝典这本书籍纪录对象 book_obj=Book.objects.create(title="python葵花宝典",state=True,price=100,publish="苹果出版社",pub_date="2012-12-12")
方法2:
book_obj=Book(title="python葵花宝典",state=True,price=100,publish="苹果出版社",pub_date="2012-12-12") book_obj.save()
例:views.py
from django.shortcuts import render,HttpResponse # Create your views here. from app01.models import Book def index(request): book_obj = Book.objects.create(title="Python葵花宝典", state=True, pub_date="2012-12-12", price=100, publish='人民出版社') book_obj.save() book_obj_2 = Book(title="Python一阳指", state=True, pub_date='2012-12-12', price=100, publish='人民出版社') book_obj_2.save() return HttpResponse("OK!")
urls.py
from django.contrib import admin from django.urls import path from app01 import views urlpatterns = [ path('admin/', admin.site.urls), path('index/', views.index), ]
用浏览器登录首页后,再查询结果:
+----+--------------------+-------+------------+--------+-----------------+ | id | title | state | pub_date | price | publish | +----+--------------------+-------+------------+--------+-----------------+ | 1 | Python葵花宝典 | 1 | 2012-12-12 | 100.00 | 人民出版社 | | 2 | Python一阳指 | 1 | 2012-12-12 | 100.00 | 人民出版社 | +----+--------------------+-------+------------+--------+-----------------+
查询表记录
查询API
<1> all(): 查询所有结果,返回的是一个queryset对象 <2> filter(**kwargs): 它包含了与所给筛选条件相匹配的对象 <3> get(**kwargs): 返回与所给筛选条件相匹配的对象,返回结果有且只有一个, 如果符合筛选条件的对象超过一个或者没有都会抛出错误。 <4> exclude(**kwargs): 它包含了与所给筛选条件不匹配的对象 <5> order_by(*field): 对查询结果排序 <6> reverse(): 对查询结果反向排序 <8> count(): 返回数据库中匹配查询(QuerySet)的对象数量。 <9> first(): 返回第一条记录 <10> last(): 返回最后一条记录 <11> exists(): 如果QuerySet包含数据,就返回True,否则返回False <12> values(*field): 返回一个ValueQuerySet——一个特殊的QuerySet,运行后得到的并不是一系列 model的实例化对象,而是一个可迭代的字典序列 <13> values_list(*field): 它与values()非常相似,它返回的是一个元组序列,values返回的是一个字典序列 <14> distinct(): 从返回结果中剔除重复纪录
在models.py的Book类中加上这两行,让屏幕打印出具体的书名:
def __str__(self): return self.title
例:views.py(注意可能需要重启下django)
from django.shortcuts import render,HttpResponse # Create your views here. from app01.models import Book def index(request): # book_obj = Book.objects.create(title="Python葵花宝典", state=True, pub_date="2012-12-12", price=100, publish='人民出版社') # book_obj.save() # book_obj_2 = Book(title="Python一阳指", state=True, pub_date='2012-12-12', price=100, publish='人民出版社') # book_obj_2.save() book_list = Book.objects.all() # print(book_list) # [obj1, obj2,...] for obj in book_list: print(obj.title, obj.price) return HttpResponse("OK!!!")
屏幕打印:
Python葵花宝典 100.00
Python一阳指 100.00
再加一本书:
book_obj_2 = Book(title="Python降龙十八掌", state=True, pub_date='2015-12-12', price=200, publish='路飞出版社') book_obj_2.save()
其他的查询API示例:(注意只要查询结果是<QuerySet>类型的都可以继续用相应方法调用,分清调用者和返回值)
from django.shortcuts import render,HttpResponse # Create your views here. from app01.models import Book def index(request): book_first_1 = Book.objects.all().first() # 调用者:queryset对象,返回值:model print("book_first:", book_first_1) book_first_2 = Book.objects.all()[2] print("book_first:", book_first_2) book_filter = Book.objects.filter(title="Python葵花宝典", price=100) # [obj1, obj2,...] print("book_filter:", book_filter) book_filter_first = Book.objects.filter(price=100).first() print("book_filter_first:", book_filter_first) book_get = Book.objects.get(price=200) # 有且只有一条结果,否则会报错 print("book_get.pub_date:", book_get.pub_date) book_exclude = Book.objects.exclude(price=200, title="Python降龙十八掌") print("book_get.pub_date:", book_exclude) book_order_by = Book.objects.order_by("price") # "-price"表示逆序 book_order_by_1 = Book.objects.order_by("price", "-id") # 当price相等时再用id排序 print("book_order_by:", book_order_by, "book_order_by_1:", book_order_by_1) book_exists = Book.objects.all().exists() print("book_exists", book_exists) book_values = Book.objects.all().values("title") print("book_values", book_values) book_values_list = Book.objects.all().values_list("price", "title") print("book_values_list", book_values_list) book_distinct = Book.objects.all().values("price").distinct() print("book_distinct:", book_distinct) return HttpResponse("OK!!!")
对应的结果:
book_first: Python葵花宝典 book_first: Python降龙十八掌 book_filter: <QuerySet [<Book: Python葵花宝典>]> book_filter_first: Python葵花宝典 book_get.pub_date: 2015-12-12 book_get.pub_date: <QuerySet [<Book: Python葵花宝典>, <Book: Python一阳指>]> book_order_by: <QuerySet [<Book: Python葵花宝典>, <Book: Python一阳指>, <Book: Python降龙十八掌>]> book_order_by_1: <QuerySet [<Book: Python一阳指>, <Book: Python葵花宝典>, <Book: Python降龙十八掌>]> book_exists True book_values <QuerySet [{'title': 'Python葵花宝典'}, {'title': 'Python一阳指'}, {'title': 'Python降龙十八掌'}]> book_values_list <QuerySet [(Decimal('100.00'), 'Python葵花宝典'), (Decimal('100.00'), 'Python一阳指'), (Decimal('200.00'), 'Python降龙十八掌')]> book_distinct: <QuerySet [{'price': Decimal('100.00')}, {'price': Decimal('200.00')}]>
模糊查询:
Book.objects.filter(price__in=[100, 200, 300]) Book.objects.filter(price__gt=100) # 大于100 Book.objects.filter(price__lt=100) # 小于100 Book.objects.filter(price__range=[100, 200]) Book.objects.filter(title__contains="python") # 包含 Book.objects.filter(title__icontains="python") # 不管大小写 Book.objects.filter(title__startswith="py") Book.objects.filter(pub_date__year=2012)
删除表记录
Book.objects.filter(price=200).delete() # 删除所有price=200的书 Book.objects.filter(pub_date__year=2005).delete() # Book.objects.filter(price=100).first().delete() Book.objects.filter(title="Python一阳指").update(title="Python六脉神剑")
# update只能被model对象调用