Django操作mysql笔记

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
#一对多和多对多在这里用法没区别

猜你喜欢

转载自blog.csdn.net/sinat_35886587/article/details/79887738
今日推荐