Django 数据库与ORM
一、数据库的配置1 django默认支持sqlite,mysql,oracle,postgresql数据库。? ???<1> sqlite ? ? ? ? ? ? django默认使用sqlite的数据库,默认自带sqlite的数据库驱动 。 ?引擎名称:django.db.backends.sqlite3 ? ? ?<2> mysql ? ? ? ? ? ? 引擎名称:django.db.backends.mysql 2 mysql驱动程序
3 在django的项目中会默认使用sqlite数据库,在settings里有如下设置:?? 如果我们想要更改数据库,需要修改如下: ? ? DATABASES =
</span><span style="color: #800000;">'</span><span style="color: #800000;">default</span><span style="color: #800000;">'</span><span style="color: #000000;">: {
</span><span style="color: #800000;">'</span><span style="color: #800000;">ENGINE</span><span style="color: #800000;">'</span>: <span style="color: #800000;">'</span><span style="color: #800000;">django.db.backends.mysql</span><span style="color: #800000;">'</span><span style="color: #000000;">,</span><span style="color: #800000;">'</span><span style="color: #800000;">NAME</span><span style="color: #800000;">'</span>: <span style="color: #800000;">'</span><span style="color: #800000;">books</span><span style="color: #800000;">'</span>,<span style="color: #008000;">#</span><span style="color: #008000;">你的数据库名称</span>
<span style="color: #800000;">'</span><span style="color: #800000;">USER</span><span style="color: #800000;">'</span>: <span style="color: #800000;">'</span><span style="color: #800000;">root</span><span style="color: #800000;">'</span>,<span style="color: #008000;">#</span><span style="color: #008000;">你的数据库用户名</span>
<span style="color: #800000;">'</span><span style="color: #800000;">PASSWORD</span><span style="color: #800000;">'</span>: <span style="color: #800000;">''</span>,<span style="color: #008000;">#</span><span style="color: #008000;">你的数据库密码</span>
<span style="color: #800000;">'</span><span style="color: #800000;">HOST</span><span style="color: #800000;">'</span>: <span style="color: #800000;">''</span>,<span style="color: #008000;">#</span><span style="color: #008000;">你的数据库主机,留空默认为localhost</span>
<span style="color: #800000;">'</span><span style="color: #800000;">PORT</span><span style="color: #800000;">'</span>: <span style="color: #800000;">'</span><span style="color: #800000;">3306</span><span style="color: #800000;">'</span>,<span style="color: #008000;">#</span><span style="color: #008000;">你的数据库端口</span>
<span style="color: #000000;"> } 注意: USER和PASSWORD分别是数据库的用户名和密码。
设置完后,再启动我们的Django项目前,我们需要激活我们的mysql。 然后,启动项目,会报错:no module named MySQLdb 这是因为django默认你导入的驱动是MySQLdb,可是MySQLdb对于py3有很大问题,所以我们需要的驱动是PyMySQL 所以,我们只需要找到项目名文件下的init,在里面写入: <span style="color: #0000ff;">import<span style="color: #000000;"> pymysqlpymysql.install_as_MySQLdb() 问题解决! 二、ORM表模型表(模型)的创建:实例:我们来假定下面这些概念,字段和关系 作者模型:一个作者有姓名。 作者详细模型:把作者的详情放到详情表,包含性别,email地址和出生日期,作者详情模型和作者模型之间是一对一的关系(one-to-one)(类似于每个人和他的身份证之间的关系),在大多数情况下我们没有必要将他们拆分成两张表,这里只是引出一对一的概念。 出版商模型:出版商有名称,地址,所在城市,省,国家和网站。 书籍模型:书籍有书名和出版日期,一本书可能会有多个作者,一个作者也可以写多本书,所以作者和书籍的关系就是多对多的关联关系(many-to-many),一本书只应该由一个出版商出版,所以出版商和书籍是一对多关联关系(one-to-many),也被称作外键。 django.db models
= models.CharField(max_length=30,verbose_name== models.CharField(,max_length=50= models.CharField(,max_length=60= models.CharField(max_length=30= models.CharField(max_length=50= </span><span style="color: #0000ff;">class</span><span style="color: #000000;"> Meta:
verbose_name </span>= <span style="color: #800000;">'</span><span style="color: #800000;">出版商</span><span style="color: #800000;">'</span><span style="color: #000000;">
verbose_name_plural </span>=<span style="color: #000000;"> verbose_name
</span><span style="color: #0000ff;">def</span> <span style="color: #800080;">__str__</span><span style="color: #000000;">(self):
</span><span style="color: #0000ff;">return</span><span style="color: #000000;"> self.name
<span style="color: #0000ff;">class<span style="color: #000000;"> Author(models.Model):name = models.CharField(max_length=30<span style="color: #000000;">) <span style="color: #0000ff;">def <span style="color: #800080;">str<span style="color: #000000;">(self): <span style="color: #0000ff;">return<span style="color: #000000;"> self.name <span style="color: #0000ff;">class<span style="color: #000000;"> AuthorDetail(models.Model): sex = models.BooleanField(max_length=1,choices=((0,<span style="color: #800000;">'<span style="color: #800000;">男<span style="color: #800000;">'),(1,<span style="color: #800000;">'<span style="color: #800000;">女<span style="color: #800000;">'<span style="color: #000000;">),)) email =<span style="color: #000000;"> models.EmailField() address = models.CharField(max_length=50<span style="color: #000000;">) birthday =<span style="color: #000000;"> models.DateField() author =<span style="color: #000000;"> models.OneToOneField(Author) <span style="color: #0000ff;">class<span style="color: #000000;"> Book(models.Model): 分析代码: ? ? ?? <1>? 每个数据模型都是django.db.models.Model的子类,它的父类Model包含了所有必要的和数据库交互的方法。并提供了一个简介漂亮的定义数据库字段的语法。 ? ? ?? <2>? 每个模型相当于单个数据库表(多对多关系例外,会多生成一张关系表),每个属性也是这个表中的字段。属性名就是字段名,它的类型(例如CharField)相当于数据库的字段类型(例如varchar)。大家可以留意下其它的类型都和数据库里的什么字段对应。 ? ? ?? <3>? 模型之间的三种关系:一对一,一对多,多对多。 ? ? ? ? ? ? ?一对一:实质就是在主外键(author_id就是foreign key)的关系基础上,给外键加了一个UNIQUE=True的属性; ? ? ? ? ? ?? 一对多:就是主外键关系;(foreign key) ? ? ? ? ? ?? 多对多:(ManyToManyField) 自动创建第三张表(当然我们也可以自己创建第三张表:两个foreign key) 1、ORM之增(create,save) app01.models *
<span style="color: #000000;"> author.save()
重点来了------->那么如何创建存在一对多或多对多关系的一本书的信息呢?(如何处理外键关系的字段如一对多的
Book.objects.create(title=<span style="color: #800000;">' <span style="color: #800000;">php<span style="color: #800000;">'<span style="color: #000000;">,publisher=pub_obj,<span style="color: #008000;">#<span style="color: #008000;">添加的为出版社对象时不使用**_id了。publication_date=<span style="color: #800000;">'<span style="color: #800000;">2017-7-7<span style="color: #800000;">'<span style="color: #000000;">,price=99)
<span style="color: #000000;"> author2=Author.objects.filter(name=<span style="color: #800000;">'<span style="color: #800000;">alvin<span style="color: #800000;">'<span style="color: #000000;">)[0] book=Book.objects.get(id=1<span style="color: #000000;">) book.authors.add(author1,author2) <span style="color: #008000;">#<span style="color: #008000;">等同于: book.authors.add(<span style="color: #000000;">[author1,author2]) book.authors.remove(<span style="color: #000000;">[author1,author2]) <span style="color: #008000;">#<span style="color: #008000;">------------------- <span style="color: #008000;">#<span style="color: #008000;">方式二: <span style="color: #008000;">#<span style="color: #008000;">取出要添加的书籍对象列表,通过一个作者对象的.book_set.add(book)添加书籍对象。 book=models.Book.objects.filter(id__gt=1<span style="color: #000000;">) authors=models.Author.objects.filter(id=1<span style="color: #000000;">)[0] authors.book_set.add(<span style="color: #000000;">book) authors.book_set.remove(*<span style="color: #000000;">book) <span style="color: #008000;">#<span style="color: #008000;">------------------- <span style="color: #008000;">#<span style="color: #008000;">方式三:取出书籍或者作者对象,直接添加对应的id. <span style="color: #000000;"> book.authors.add(1) <span style="color: #008000;">#<span style="color: #008000;">book.authors.add(1,2) 可一次添加多个id,已存在的id不会重复添加 book.authors.remove(1<span style="color: #000000;">) authors.book_set.add(1<span style="color: #000000;">) authors.book_set.remove(1<span style="color: #000000;">) <span style="color: #008000;">#<span style="color: #008000;">注意: 如果第三张表是通过models.ManyToManyField()自动创建的,那么绑定关系只有上面一种方式<span style="color: #008000;"> <span style="color: #008000;"> 如果第三张表是自己创建的:
<span style="color: #008000;">#<span style="color: #008000;"> 那么就还有一种方式:
2、ORM之删(delete)>>> Book.objects.filter(id=1).delete()
(3,{'app01.Book_authors': 2,'app01.Book': 1})
我们表面上删除了一条信息,实际却删除了三条,因为我们删除的这本书在Book_authors表中有两条相关信息,这种删除方式就是django默认的级联删除。 3、ROM之改(update和save)实例: ? ?? 注意: <1> 第二种方式修改不能用get的原因是:update是QuerySet对象的方法,get返回的是一个model对象,它没有update方法,而filter返回的是一个QuerySet对象(filter里面的条件可能有多个条件符合,比如name='alvin',可能有两个name='alvin'的行数据)。 <2>在“插入和更新数据”小节中,我们有提到模型的 save() 方法,这个方法会更新一行里的所有列。而某些情况下,我们只需要更新行里的某几列。
models.Book.objects.filter(id=3).update(title=
<span style="color: #008000;"># <span style="color: #008000;">--------------- save方法会将所有属性重新设定一遍,效率低-----------obj=models.Book.objects.filter(id=3<span style="color: #000000;">)[0] obj.title=<span style="color: #800000;">"<span style="color: #800000;">Python<span style="color: #800000;">"<span style="color: #000000;"> obj.save() <span style="color: #008000;">#<span style="color: #008000;"> SELECT "app01_book"."id","app01_book"."title","app01_book"."price",<span style="color: #008000;"> <span style="color: #008000;"> "app01_book"."color","app01_book"."page_num",<span style="color: #008000;"> <span style="color: #008000;"> "app01_book"."publisher_id" FROM "app01_book" WHERE "app01_book"."id" = 3 LIMIT 1; <span style="color: #008000;"><span style="color: #008000;"><span style="color: #008000;"> UPDATE "app01_book" SET "title" = 'Python',"price" = 3333,"color" = 'red',"page_num" = 556,<span style="color: #008000;"><span style="color: #008000;"> "publisher_id" = 1 WHERE "app01_book"."id" = 3;此外,update()方法对于任何结果集(QuerySet)均有效,这意味着你可以同时更新多条记录update()方法会返回一个整型数值,表示受影响的记录条数。 注意,这里因为update返回的是一个整形,所以没法用query属性;对于每次创建一个对象,想显示对应的raw sql,需要在settings加上日志记录部分: LOGGING =: 1::: [:
4、ORM之查(filter和value)4.1 查询API<span style="color: #008000;"># <span style="color: #008000;"> <1>filter(**kwargs): 它包含了与所给筛选条件相匹配的对象<span style="color: #008000;">#<span style="color: #008000;"> <2>all(): 查询所有结果 <span style="color: #008000;">#<span style="color: #008000;"> <3>get(**kwargs): 返回与所给筛选条件相匹配的对象,返回结果有且只有一个,如果符合筛选条件的对象超过一个或者没有都会抛出错误。 <span style="color: #008000;">#<span style="color: #008000;">-----------下面的方法都是对查询的结果再进行处理:比如 objects.filter.values()-------- <span style="color: #008000;">#<span style="color: #008000;"> <4>values(*field): 返回一个ValueQuerySet——一个特殊的QuerySet,运行后得到的并不是一系列 model的实例化对象,而是一个可迭代的字典序列 <span style="color: #008000;">#<span style="color: #008000;"> <5>exclude(**kwargs): 它包含了与所给筛选条件不匹配的对象 <span style="color: #008000;">#<span style="color: #008000;"> <6>order_by(*field): 对查询结果排序 <span style="color: #008000;">#<span style="color: #008000;"> <7>reverse(): 对查询结果反向排序 <span style="color: #008000;">#<span style="color: #008000;"> <8>distinct(): 从返回结果中剔除重复纪录 <span style="color: #008000;">#<span style="color: #008000;"> <9>values_list(*field): 它与values()非常相似,它返回的是一个元组序列,values返回的是一个字典序列 <span style="color: #008000;">#<span style="color: #008000;"> <10>count(): 返回数据库中匹配查询(QuerySet)的对象数量。 <span style="color: #008000;">#<span style="color: #008000;"> <11>first(): 返回第一条记录 <span style="color: #008000;">#<span style="color: #008000;"> <12>last(): 返回最后一条记录 <span style="color: #008000;">#<span style="color: #008000;"> <13>exists(): 如果QuerySet包含数据,就返回True,否则返回False ---------------了不起的双下划线(__)之单表条件查询----------------
<span style="color: #008000;">#<span style="color: #008000;"> models.Tb1.objects.filter(idlt=10,idgt=1) # 获取id大于1 且 小于10的值<span style="color: #008000;"> <span style="color: #008000;"> models.Tb1.objects.filter(id__in=[11,22,33]) # 获取id等于11、22、33的数据<span style="color: #008000;"><span style="color: #008000;"> models.Tb1.objects.exclude(id__in=[11,33]) # not in<span style="color: #008000;"><span style="color: #008000;"> models.Tb1.objects.filter(name__contains="ven")<span style="color: #008000;"><span style="color: #008000;"> models.Tb1.objects.filter(name__icontains="ven") # icontains大小写不敏感<span style="color: #008000;"><span style="color: #008000;"> models.Tb1.objects.filter(id__range=[1,2]) # 范围bettwen and<span style="color: #008000;"><span style="color: #008000;"> startswith,istartswith,endswith,iendswith,4.2?QuerySet与惰性机制所谓惰性机制:Publisher.objects.all()或者.filter()等都只是返回了一个QuerySet(查询结果集对象),它并不会马上执行sql,而是当调用QuerySet的时候才执行。 QuerySet特点: ? ? ?? <1>? 可迭代的 ? ? ?? <2>? 可切片
QuerySet的高效使用: <1>
Django的queryset对应于数据库的若干记录(row),通过可选的查询来过滤。例如,下面的代码会得到数据库中名字为‘Dave’的所有的人:person_set </span>= Person.objects.filter(first_name=<span style="color: #800000;">"</span><span style="color: #800000;">Dave</span><span style="color: #800000;">"</span><span style="color: #000000;">)
上面的代码并没有运行任何的数据库查询。你可以使用person_set,给它加上一些过滤条件,或者将它传给某个函数,这些操作都不会发送给数据库。这是对的,因为数据库查询是显著影响web应用性能的因素之一。
<2><span style="color: #000000;">要真正从数据库获得数据,你可以遍历queryset或者使用if queryset,总之你用到数据时就会执行sql.为了验证这些,需要在settings里加入 LOGGING(验证方式)obj=models.Book.objects.filter(id=3<span style="color: #000000;">) <span style="color: #008000;">#<span style="color: #008000;"> for i in obj: <span style="color: #008000;">#<span style="color: #008000;"> print(i)
<3>=models.Book.objects.filter(id=3 </span><span style="color: #008000;">#</span><span style="color: #008000;"> for i in obj:</span>
<span style="color: #008000;">#</span><span style="color: #008000;"> print(i)</span>
<span style="color: #008000;">#</span><span style="color: #008000;"># models.Book.objects.filter(id=3).update(title="GO")</span>
<span style="color: #008000;">#</span><span style="color: #008000;"># obj_new=models.Book.objects.filter(id=3)</span>
<span style="color: #008000;">#</span><span style="color: #008000;"> for i in obj:</span>
<span style="color: #008000;">#</span><span style="color: #008000;"> print(i) #LOGGING只会打印一次</span>
<4> obj </span>= Book.objects.filter(id=4<span style="color: #000000;">)
</span><span style="color: #008000;">#</span><span style="color: #008000;"> exists()的检查可以避免数据放入queryset的cache。</span>
<span style="color: #0000ff;">if</span><span style="color: #000000;"> obj.exists():
</span><span style="color: #0000ff;">print</span>(<span style="color: #800000;">"</span><span style="color: #800000;">hello world!</span><span style="color: #800000;">"</span><span style="color: #000000;">)
<5><span style="color: #000000;">当queryset非常巨大时,cache会成为问题处理成千上万的记录时,将它们一次装入内存是很浪费的。更糟糕的是,巨大的queryset可能会锁住系统进程,让你的程序濒临崩溃。要避免在遍历数据的同时产生queryset cache,可以使用iterator()方法来获取数据,处理完数据就将其丢弃。objs =<span style="color: #000000;"> Book.objects.all().iterator() <span style="color: #008000;">#<span style="color: #008000;"> iterator()可以一次只从数据库获取少量数据,这样可以节省内存 <span style="color: #0000ff;">for obj <span style="color: #0000ff;">in<span style="color: #000000;"> objs: <span style="color: #0000ff;">print<span style="color: #000000;">(obj.name) <span style="color: #008000;">#<span style="color: #008000;">BUT,再次遍历没有打印,因为迭代器已经在上一次遍历(next)到最后一次了,没得遍历了 <span style="color: #0000ff;">for obj <span style="color: #0000ff;">in<span style="color: #000000;"> objs: <span style="color: #0000ff;">print<span style="color: #000000;">(obj.name)
<span style="color: #000000;"> (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |