文档章节

Django 的数据库查询

V字仇杀
 V字仇杀
发布于 2016/08/17 17:47
字数 1619
阅读 3
收藏 0

Python代码  收藏代码

  1. class Blog(models.Model):  
  2.     name = models.CharField(max_length=100)  
  3.     tagline = models.TextField()  
  4.   
  5.     def __unicode__(self):  
  6.         return self.name  
  7.   
  8. class Author(models.Model):  
  9.     name = models.CharField(max_length=50)  
  10.     email = models.EmailField()  
  11.   
  12.     def __unicode__(self):  
  13.         return self.name  
  14.   
  15. class Entry(models.Model):  
  16.     blog = models.ForeignKey(Blog)  
  17.     headline = models.CharField(max_length=255)  
  18.     body_text = models.TextField()  
  19.     pub_date = models.DateTimeField()  
  20.     authors = models.ManyToManyField(Author)  
  21.   
  22.     def __unicode__(self):  
  23.         return self.headline  


这是model,有blog,author,以及entry;其中entry分别与blog与author表关联,entry与blog表是通过外键(models.ForeignKey())相连,属于一对多的关系,即一个entry对应多个blog,entry与author是多对多的关系,通过modles.ManyToManyField()实现。 
一、插入数据库,用save()方法实现,如下: 
>>> from mysite.blog.models import Blog 
>>> b = Blog(name='Beatles Blog', tagline='All the latest Beatles news.') 
>>> b.save() 

二、更新数据库,也用save()方法实现,如下: 
>> b5.name = 'New name' 
>> b5.save() 


保存外键和多对多关系的字段,如下例子: 
更新外键字段和普通的字段一样,只要指定一个对象的正确类型。 
>>> cheese_blog = Blog.objects.get(name="Cheddar Talk") 
>>> entry.blog = cheese_blog 
>>> entry.save() 

更新多对多字段时又一点不太一样,使用add()方法添加相关联的字段的值。 
>> joe = Author.objects.create(name="Joe") 
>> entry.authors.add(joe) 

三、检索对象 

>>> Blog.objects 
<django.db.models.manager.Manager object at ...> 
>>> b = Blog(name='Foo', tagline='Bar') 
>>> b.objects 
Traceback: 
    ... 
AttributeError: "Manager isn't accessible via Blog instances." 

1、检索所有的对象 

>>> all_entries = Entry.objects.all() 

使用all()方法返回数据库中的所有对象。 

2、检索特定的对象 
使用以下两个方法: 
fileter(**kwargs) 
返回一个与参数匹配的QuerySet,相当于等于(=). 
exclude(**kwargs) 
返回一个与参数不匹配的QuerySet,相当于不等于(!=)。 

Entry.objects.filter(pub_date__year=2006) 
不使用Entry.objects.all().filter(pub_date__year=2006),虽然也能运行,all()最好再获取所有的对象时使用。 
上面的例子等同于的sql语句: 
slect * from entry where pub_date_year='2006' 

链接过滤器: 
>>> Entry.objects.filter( 
...     headline__startswith='What' 
... ).exclude( 
...     pub_date__gte=datetime.now() 
... ).filter( 
...     pub_date__gte=datetime(2005, 1, 1) 
... ) 

最后返回的QuerySet是headline like 'What%' and put_date<now() and pub_date>2005-01-01 

另外一种方法: 
>> q1 = Entry.objects.filter(headline__startswith="What") 
>> q2 = q1.exclude(pub_date__gte=datetime.now()) 
>> q3 = q1.filter(pub_date__gte=datetime.now()) 
这种方法的好处是可以对q1进行重用。 

QuerySet是延迟加载 
只在使用的时候才会去访问数据库,如下: 
>>> q = Entry.objects.filter(headline__startswith="What") 
>>> q = q.filter(pub_date__lte=datetime.now()) 
>>> q = q.exclude(body_text__icontains="food") 
>>> print q 
在print q时才会访问数据库。 

其他的QuerySet方法 
>>> Entry.objects.all()[:5] 
这是查找前5个entry表里的数据 

>>> Entry.objects.all()[5:10] 
这是查找从第5个到第10个之间的数据。 

>>> Entry.objects.all()[:10:2] 
这是查询从第0个开始到第10个,步长为2的数据。 

>>> Entry.objects.order_by('headline')[0] 
这是取按headline字段排序后的第一个对象。 

>>> Entry.objects.order_by('headline')[0:1].get() 
这和上面的等同的。 

>>> Entry.objects.filter(pub_date__lte='2006-01-01') 
等同于SELECT * FROM blog_entry WHERE pub_date <= '2006-01-01'; 

>>> Entry.objects.get(headline__exact="Man bites dog") 
等同于SELECT ... WHERE headline = 'Man bites dog'; 

>>> Blog.objects.get(id__exact=14)  # Explicit form 
>>> Blog.objects.get(id=14)         # __exact is implied 
这两种方式是等同的,都是查找id=14的对象。 

>>> Blog.objects.get(name__iexact="beatles blog") 
查找name="beatles blog"的对象,不去饭大小写。 

Entry.objects.get(headline__contains='Lennon') 
等同于SELECT ... WHERE headline LIKE '%Lennon%'; 

startswith 等同于sql语句中的 name like 'Lennon%', 
endswith等同于sql语句中的 name like '%Lennon'. 

>>> Entry.objects.filter(blog__name__exact='Beatles Blog') 
查找entry表中外键关系blog_name='Beatles Blog'的Entry对象。 

>>> Blog.objects.filter(entry__headline__contains='Lennon') 
查找blog表中外键关系entry表中的headline字段中包含Lennon的blog数据。 

Blog.objects.filter(entry__author__name='Lennon') 
查找blog表中外键关系entry表中的author字段中包含Lennon的blog数据。 

Blog.objects.filter(entry__author__name__isnull=True) 
Blog.objects.filter(entry__author__isnull=False,entry__author__name__isnull=True) 
查询的是author_name为null的值 

Blog.objects.filter(entry__headline__contains='Lennon',entry__pub_date__year=2008) 
Blog.objects.filter(entry__headline__contains='Lennon').filter(  entry__pub_date__year=2008) 
这两种查询在某些情况下是相同的,某些情况下是不同的。第一种是限制所有的blog数据的,而第二种情况则是第一个filter是 
限制blog的,而第二个filter则是限制entry的 

>>> Blog.objects.get(id__exact=14) # Explicit form 
>>> Blog.objects.get(id=14) # __exact is implied 
>>> Blog.objects.get(pk=14) # pk implies id__exact 
等同于select * from where id=14 


# Get blogs entries with id 1, 4 and 7 
>>> Blog.objects.filter(pk__in=[1,4,7]) 
等同于select * from where id in{1,4,7} 
# Get all blog entries with id > 14 
>>> Blog.objects.filter(pk__gt=14) 
等同于select * from id>14 

>>> Entry.objects.filter(blog__id__exact=3) # Explicit form 
>>> Entry.objects.filter(blog__id=3)        # __exact is implied 
>>> Entry.objects.filter(blog__pk=3)        # __pk implies __id__exact 
这三种情况是相同的 


>>> Entry.objects.filter(headline__contains='%') 
等同于SELECT ... WHERE headline LIKE '%\%%'; 


Caching and QuerySets 

>>> print [e.headline for e in Entry.objects.all()] 
>>> print [e.pub_date for e in Entry.objects.all()] 
应改写为: 
>> queryset = Poll.objects.all() 
>>> print [p.headline for p in queryset] # Evaluate the query set. 
>>> print [p.pub_date for p in queryset] # Re-use the cache from the evaluation.、 
这样利用缓存,减少访问数据库的次数。 

四、用Q对象实现复杂的查询 

Q(question__startswith='Who') | Q(question__startswith='What') 
等同于WHERE question LIKE 'Who%' OR question LIKE 'What%' 


Poll.objects.get( 
    Q(question__startswith='Who'), 
    Q(pub_date=date(2005, 5, 2)) | Q(pub_date=date(2005, 5, 6)) 

等同于SELECT * from polls WHERE question LIKE 'Who%' AND (pub_date = '2005-05-02' OR pub_date = '2005-05-06') 

Poll.objects.get( 
    Q(pub_date=date(2005, 5, 2)) | Q(pub_date=date(2005, 5, 6)), 
    question__startswith='Who') 
等同于Poll.objects.get(question__startswith='Who', Q(pub_date=date(2005, 5, 2)) | Q(pub_date=date(2005, 5, 6))) 


五、比较对象 

>>> some_entry == other_entry 
>>> some_entry.id == other_entry.id 


六、删除 

Entry.objects.filter(pub_date__year=2005).delete() 


b = Blog.objects.get(pk=1) 
# This will delete the Blog and all of its Entry objects. 
b.delete() 

Entry.objects.all().delete() 
删除所有 

七、一次更新多个值 

# Update all the headlines with pub_date in 2007. 
Entry.objects.filter(pub_date__year=2007).update(headline='Everything is the same') 

>>> b = Blog.objects.get(pk=1) 
# Change every Entry so that it belongs to this Blog. 
>>> Entry.objects.all().update(blog=b) 

如果用save()方法,必须一个一个进行保存,需要对其就行遍历,如下: 
for item in my_queryset: 
    item.save() 

关联对象 

one-to-many 
>>> e = Entry.objects.get(id=2) 
>>> e.blog # Returns the related Blog object. 


>>> e = Entry.objects.get(id=2) 
>>> e.blog = some_blog 
>>> e.save() 

>>> e = Entry.objects.get(id=2) 
>>> e.blog = None 
>>> e.save() # "UPDATE blog_entry SET blog_id = NULL ...;" 

>>> e = Entry.objects.get(id=2) 
>>> print e.blog  # Hits the database to retrieve the associated Blog. 
>>> print e.blog  # Doesn't hit the database; uses cached version. 

>>> e = Entry.objects.select_related().get(id=2) 
>>> print e.blog  # Doesn't hit the database; uses cached version. 
>>> print e.blog  # Doesn't hit the database; uses cached version 

>>> b = Blog.objects.get(id=1) 
>>> b.entry_set.all() # Returns all Entry objects related to Blog. 

# b.entry_set is a Manager that returns QuerySets. 
>>> b.entry_set.filter(headline__contains='Lennon') 
>>> b.entry_set.count() 


>>> b = Blog.objects.get(id=1) 
>>> b.entries.all() # Returns all Entry objects related to Blog. 
# b.entries is a Manager that returns QuerySets. 
>>> b.entries.filter(headline__contains='Lennon') 
>>> b.entries.count() 

You cannot access a reverse ForeignKey Manager from the class; it must be accessed from an instance: 
>>> Blog.entry_set 

add(obj1, obj2, ...) 
    Adds the specified model objects to the related object set. 
create(**kwargs) 
    Creates a new object, saves it and puts it in the related object set. Returns the newly created object. 
remove(obj1, obj2, ...) 
    Removes the specified model objects from the related object set. 
clear() 
    Removes all objects from the related object set. 
    
many-to-many类型: 
e = Entry.objects.get(id=3) 
e.authors.all() # Returns all Author objects for this Entry. 
e.authors.count() 
e.authors.filter(name__contains='John') 
a = Author.objects.get(id=5) 
a.entry_set.all() # Returns all Entry objects for this Author. 

one-to-one 类型: 
class EntryDetail(models.Model): 
    entry = models.OneToOneField(Entry) 
    details = models.TextField() 

ed = EntryDetail.objects.get(id=2) 
ed.entry # Returns the related Entry object 


使用sql语句进行查询: 

def my_custom_sql(self): 
    from django.db import connection 
    cursor = connection.cursor() 
    cursor.execute("SELECT foo FROM bar WHERE baz = %s", [self.baz]) 
    row = cursor.fetchone() 
    return row 

本文转载自:

V字仇杀

V字仇杀

粉丝 5
博文 214
码字总数 35636
作品 0
杭州
程序员
私信 提问
Django 实战1:搭建属于自己社工查询系统(下)

上篇文章已经完成框架搭建,本文接着上篇的内容继续讲解。本片主要的说三点内容,分别是:根据条件查询数据、根据查询结果显示不同内容、将查询数据填充到页面上。 1 逻辑优化 在上篇文章,我...

猴哥Yuri
2018/04/15
0
0
Django 实战1:搭建属于自己社工查询系统(上)

前面的文章已经把模板、模型、视图、表单等知识点逐一讲解,大家已经熟悉它们具体用法。但如何将其串联起来还一筹莫展。本篇文章分享我之前做过的一个小项目,帮助大家抹开这一层迷雾。 1 想...

猴哥Yuri
2018/04/09
0
0
Django数据库连接丢失问题

问题 在Django中使用mysql偶尔会出现数据库连接丢失的情况,错误通常有如下两种 查询mysql全局变量可以看到,此变量表示连接空闲时间。如果客户端使用一个连接查询多次数据库,如果连续查询则...

张豪飞
2018/12/28
433
2
介绍两个Python web框架:Django & Tornado

在各种语言平台中,python涌现的web框架恐怕是最多的;猜想原因应该是在py中构造框架十分简单,使得轮子不断被发明。 这里记述一下我了解过的两个py web框架,供大家参考,希望能起他山之石的...

宁宁123韩
2013/04/14
1K
0
djongo:Django和MongoDB连接器

在Django项目中使用MongoDB作为后端数据库,且不改变Django的ORM框架。实现Django用户管理程序对MongoDB数据库中文件的增加和修改。 用法 1.pip install djongo 2.在Django项目下的setting.p...

p柯西
2018/06/20
57
0

没有更多内容

加载失败,请刷新页面

加载更多

OSChina 周六乱弹 —— 不要在领导修风扇的时候打开电扇

Osc乱弹歌单(2019)请戳(这里) 【今日歌曲】 @巴拉迪维 :《Whats Up》 主唱妹子 Lina Perry 的嗓音实在太有力了,收放自如的自信才能唱出这么优秀的歌吧!#今日歌曲推荐# 《Whats Up》-...

小小编辑
今天
11
0
SpringBoot集成Elasticsearch并进行增删改查操作

一、创建工程 使用IntelliJ创建SpringBoot工程 SpringBoot版本为2.0.4 ElasticSearch为5.6.10 删掉蓝框中的文件(如上) 最后我们的目录结构(如下) 下面pom文件主要修改的是把spring boot从Int...

一字见心
今天
5
0
x001-版本介绍

python版本介绍 目前有2 和 3 有很多企业用的代码是2版本,随着技术的发展,以后用3的会成为大趋势 python3的安装 yum -y install wget gcc zlib-devel bzip2-devel openssl-devel ncurses-d...

侠客行之石头
今天
5
0
聊聊rocketmq的TransientStorePool

序 本文主要研究一下rocketmq的TransientStorePool TransientStorePool rocketmq-all-4.6.0-source-release/store/src/main/java/org/apache/rocketmq/store/TransientStorePool.java publi......

go4it
昨天
6
0
笔记

场外借贷, 质押 ,托管, 永续合约. 场外借贷,n签合同. 新功能 证券交易组负责中信证券机构及个人投资交易相关系统,服务机构及个人投资客户, 涉及到两融、期权、 期货、做市等境内境外创新业...

MtrS
昨天
6
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部