Django默认操作的是sqlite,如果要操作sqlite3不需要修改setting.py,直接添加url,在models里创建类。以及添加视图图对应的函数即可。
如果要与mysql进行交互。则要先修改setting.py里面的设置。
如下:
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': 'django_orm', #你的数据库名称,使用之前要在mysql里创建
'USER': '', #你的数据库用户名
'PASSWORD': '', #你的数据库密码
'HOST': '', #你的数据库主机,留空默认为localhost
'PORT': '3306', #你的数据库端口
}
}
然后在项目的init.py文件里加入
import pymysql
pymysql.install_as_MySQLdb()
不然Django会提示找不到模块。
然后,在models里创建类。
所谓的ORM操作,用于实现面向对象编程语言里不同类型系统的数据之间的转换,换言之,就是用面向对象的方式去操作数据库的创建表以及增删改查等操作。
我们可以理解为,比如创建表,可以认为在models里创建类,类的属性名,对应表头名,然后我们在创建属性是主要是给属性指定数据类型以及相关约束。
例如创建一个Book类:
class Book(models.Model)
name = models.CharField(max_length = 20)
price= models.IntegerField()
pub_date=models.DateField()
author=models.CharField(max_length = 32,null = False)
注意:我们创建的类必须继承models.Model类
然后,在Terminal里输入命令:
python manage.py makemigrations
python manage.py migrate
如果执行没有出错可以在mysql里看到相应的表。
mysql> show tables;
+—————————-+
| Tables_in_django_orm |
+—————————-+
| app01_book |
| auth_group |
| auth_group_permissions |
| auth_permission |
| auth_user |
| auth_user_groups |
| auth_user_user_permissions |
| django_admin_log |
| django_content_type |
| django_migrations |
| django_session |
+—————————-+
12 rows in set (0.00 sec)
输入查看,dsec app01_book;
mysql> desc app01_book;
+———-+————-+——+—–+———+—————-+
| Field | Type | Null | Key | Default | Extra |
+———-+————-+——+—–+———+—————-+
| id | int(11) | NO | PRI | NULL | auto_increment |
| name | varchar(20) | NO | | NULL | |
| price | int(11) | NO | | NULL | |
| pub_date | date | NO | | NULL | |
| author | varchar(32) | NO | | NULL | |
+———-+————-+——+—–+———+—————-+
得到表结果,可以看出django给我们自动添加了id并设置为主键 ,其他都是根据我们的Book类里设置的。
接下来我就可以进行增删改查操作
在views试图文件里先导入models
from app01.models import * # app01是我们创建的app
然后就可以创建视图函数操作了,
这里创建一个添加的函数
def add_book(request):
# 添加记录方法1
# b = Book(name = ‘python基础’, price = ‘20000’, author = ‘Sky’ ,pub_date = ‘2017-1-2’)
# b.save()
# 添加记录方法2
Book.objects.create(name = ‘python精通’, price = ‘200’, author = ‘Sky’ ,pub_date = ‘2017-12-12’)
# Book.objects.create(**dic) 如果前端传来字典的数据能对应上就可以直接全字典取
return HttpResponse("添加成功")
注:所有视图函数需要在urls里添加到path里。
表记录添加
假设在models中创建了Book类
添加记录方法1
b = Book(name = ‘python基础’, price = ‘20000’, author = ‘Sky’ ,pub_date = ‘2017-1-2’)
b.save()
添加记录方法2
Book.objects.create(name = ‘python精通’, price = ‘200’, author = ‘Sky’ ,pub_date = ‘2017-12-12’)
表记录修改
方法1(推荐)
Book.objects.filter(id=’2’).update(author=’sleep_cat’)
方法2
b=Book.objects.get(author=’sleep_cat’)
b.price=’1000’
b.save()
查询相关API:
<1>filter(**kwargs): 它包含了与所给筛选条件相匹配的对象
<2>all(): 查询所有结果
<3>get(**kwargs): 返回与所给筛选条件相匹配的对象,返回结果有且只有一个,如果符合筛选条件的对象超过一个或者没有都会抛出错误。
———–下面的方法都是对查询的结果再进行处理:比如 objects.filter.values()——–
<4>values(*field): 返回一个ValueQuerySet——一个特殊的QuerySet,运行后得到的并不是一系列 model的实例化对象,而是一个可迭代的字典序列
<5>exclude(**kwargs): 它包含了与所给筛选条件不匹配的对象
<6>order_by(*field): 对查询结果排序
<7>reverse(): 对查询结果反向排序
<8>distinct(): 从返回结果中剔除重复纪录
<9>values_list(*field): 它与values()非常相似,它返回的是一个元组序列,values返回的是一个字典序列
<10>count(): 返回数据库中匹配查询(QuerySet)的对象数量。
<11>first(): 返回第一条记录
<12>last(): 返回最后一条记录
<13>exists(): 如果QuerySet包含数据,就返回True,否则返回False。
扩展查询,有时候DJANGO的查询API不能方便的设置查询条件,提供了另外的扩展查询方法extra:
extra(select=None, where=None, params=None, tables=None,order_by=None, select_params=None
(1) Entry.objects.extra(select={‘is_recent’: “pub_date > ‘2006-01-01’”})
(2) Blog.objects.extra(
select=SortedDict([(‘a’, ‘%s’), (‘b’, ‘%s’)]),
select_params=(‘one’, ‘two’))
(3) q = Entry.objects.extra(select={‘is_recent’: “pub_date > ‘2006-01-01’”})
q = q.extra(order_by = [‘-is_recent’])
(4) Entry.objects.extra(where=[‘headline=%s’], params=[‘Lennon’])
QuerySet特点
Django返回的数据类型–queryset
利用Class.object.filter()或者Class.object.all()等方法返回的结果都是queryset,可以理解为一个对象集,即数据记录集。
QuerSet数据集有两个特点
1、可切片(类似python列表)
2、可迭代
#objs=models.Book.objects.all()#[obj1,obj2,ob3…]
#QuerySet: 可迭代
# for obj in objs:#每一obj就是一个行对象
# print(“obj:”,obj)
# QuerySet: 可切片
# print(objs[1])
# print(objs[1:4])
# print(objs[::-1])
注:自行练习以上代码体会
<1>Django的queryset是惰性的
Django的queryset对应于数据库的若干记录(row),通过可选的查询来过滤。例如,下面的代码会得
到数据库中名字为‘Dave’的所有的人:person_set = Person.objects.filter(first_name="Dave")
上面的代码并没有运行任何的数据库查询。你可以使用person_set,给它加上一些过滤条件,或者将它传给某个函数,
这些操作都不会发送给数据库。这是对的,因为数据库查询是显著影响web应用性能的因素之一。
<2>要真正从数据库获得数据,你可以遍历queryset或者使用if queryset,总之你用到数据时就会执行sql.
为了验证这些,需要在settings里加入 LOGGING(验证方式)
obj=models.Book.objects.filter(id=3)
# for i in obj:
# print(i)
# if obj:
# print("ok")
<3>queryset是具有cache的
当你遍历queryset时,所有匹配的记录会从数据库获取,然后转换成Django的model。这被称为执行
(evaluation).这些model会保存在queryset内置的cache中,这样如果你再次遍历这个queryset,
你不需要重复运行通用的查询。
obj=models.Book.objects.filter(id=3)
# for i in obj:
# print(i)
## models.Book.objects.filter(id=3).update(title="GO")
## obj_new=models.Book.objects.filter(id=3)
# for i in obj:
# print(i) #LOGGING只会打印一次
<4>
简单的使用if语句进行判断也会完全执行整个queryset并且把数据放入cache,虽然你并不需要这些
数据!为了避免这个,可以用exists()方法来检查是否有数据:
obj = Book.objects.filter(id=4)
# exists()的检查可以避免数据放入queryset的cache。
if obj.exists():
print("hello world!")
<5>当queryset非常巨大时,cache会成为问题
处理成千上万的记录时,将它们一次装入内存是很浪费的。更糟糕的是,巨大的queryset可能会锁住系统
进程,让你的程序濒临崩溃。要避免在遍历数据的同时产生queryset cache,可以使用iterator()方法
来获取数据,处理完数据就将其丢弃。
objs = Book.objects.all().iterator()
# iterator()可以一次只从数据库获取少量数据,这样可以节省内存
for obj in objs:
print(obj.name)
#BUT,再次遍历没有打印,因为迭代器已经在上一次遍历(next)到最后一次了,没得遍历了
for obj in objs:
print(obj.name)
#当然,使用iterator()方法来防止生成cache,意味着遍历同一个queryset时会重复执行查询。所以使
#用iterator()的时候要当心,确保你的代码在操作一个大的queryset时没有重复执行查询
总结:
queryset的cache是用于减少程序对数据库的查询,在通常的使用下会保证只有在需要的时候才会查询数据库。
使用exists()和iterator()方法可以优化程序对内存的使用。不过,由于它们并不会生成queryset cache,可能
会造成额外的数据库查询。
———>对象查询,单表条件查询,多表条件关联查询
——————–对象形式的查找————————– # 正向查找 ret1=models.Book.objects.first() print(ret1.title) print(ret1.price) print(ret1.publisher) print(ret1.publisher.name) #因为一对多的关系所以ret1.publisher是一个对象,而不是一个queryset集合 # 反向查找 ret2=models.Publish.objects.last() print(ret2.name) print(ret2.city) #如何拿到与它绑定的Book对象呢? print(ret2.book_set.all()) #ret2.book_set是一个queryset集合 #—————了不起的双下划线()之单表条件查询—————- # models.Tb1.objects.filter(id__lt=10, id__gt=1) # 获取id大于1 且 小于10的值 # # models.Tb1.objects.filter(id__in=[11, 22, 33]) # 获取id等于11、22、33的数据 # models.Tb1.objects.exclude(id__in=[11, 22, 33]) # not in # # models.Tb1.objects.filter(name__contains=”ven”) # models.Tb1.objects.filter(name__icontains=”ven”) # icontains大小写不敏感 # # models.Tb1.objects.filter(id__range=[1, 2]) # 范围bettwen and # # startswith,istartswith, endswith, iendswith, #—————-了不起的双下划线()之多表条件关联查询————— # 正向查找(条件) # ret3=models.Book.objects.filter(title=’Python’).values(‘id’) # print(ret3)#[{‘id’: 1}]
#正向查找(条件)之一对多
ret4=models.Book.objects.filter(title='Python').values('publisher__city')
print(ret4) #[{'publisher__city': '北京'}]
#正向查找(条件)之多对多
ret5=models.Book.objects.filter(title='Python').values('author__name')
print(ret5)
ret6=models.Book.objects.filter(author__name="alex").values('title')
print(ret6)
#注意
#正向查找的publisher__city或者author__name中的publisher,author是book表中绑定的字段
#一对多和多对多在这里用法没区别
反向查找(条件)
#反向查找之一对多:
ret8=models.Publisher.objects.filter(book__title='Python').values('name')
print(ret8)#[{'name': '人大出版社'}] 注意,book__title中的book就是Publisher的关联表名
ret9=models.Publisher.objects.filter(book__title='Python').values('book__authors')
print(ret9)#[{'book__authors': 1}, {'book__authors': 2}]
#反向查找之多对多:
ret10=models.Author.objects.filter(book__title='Python').values('name')
print(ret10)#[{'name': 'alex'}, {'name': 'alvin'}]
#注意
#正向查找的book__title中的book是表名Book
#一对多和多对多在这里用法没区别