[TOC]
模型与数据库:一一对应
创建、查询操作
注意Person.objects.xx()的返回值类型!
# models.py
class Person(models.Model):
name = models.CharField(max_length=30)
age = models.IntegerField()
$ python manage.py shell
In [1]: from learn.models import Person
In [2]: Person.objects.create(name="suyn",age=26)
Out[2]: <Person: Person object>
In [3]: Person.objects.get(name="suyn")
Out[3]: <Person: Person object>
In [4]: import keyword
In [5]: print keyword.kwlist #打出所有的关键字
['and', 'as', 'assert', 'break', 'class', 'continue', 'def', 'del', 'elif', 'else', 'except', 'exec', 'finally', 'for', 'from', 'global', 'if', 'import', 'in', 'is', 'lambda', 'not', 'or', 'pass', 'print', 'raise', 'return', 'try', 'while', 'with', 'yield']
查询结果中显示<Person: Person object>,这里并没有显示出与suyn的相关信息,如果用户多了就无法知道查询出来的到底是谁,查询结果是否正确,我们重新修改models.py。
注:name 和 age 等字段中不能有__和关键字
双下划线,在Django QuerySet API中有特殊含义:用于关系,包含,不区分大小写,以什么开头或结尾,日期的大于小于,正则等;name 是合法的,student_name 也合法,但是student__name不合法。
# models.py
class Person(models.Model):
name = models.CharField(max_length=30)
age = models.IntegerField()
def __unicode__(self):
return self.name
$ python manage.py shell
In [1]: from learn.models import Person
In [2]: Person.objects.get(name="suyn")
Out[2]: <Person: suyn> #get方法返回一个Person对象,返回多个要用filter/exclude/all
In [3]: p = Person(name="sophia",age=20)
In [4]: Person.objects.all()
Out[4]: <QuerySet [<Person: suyn>]> #all方法返回QuerySet一个集合,像列表
In [5]: p.save() #保存后才真正更新到数据库
In [6]: Person.objects.all()
Out[6]: <QuerySet [<Person: suyn>, <Person: sophia>]>
In [7]: p = Person(name="HSZ")
In [9]: p.age=18
In [11]: p.save() #所有必须非空属性有值才可以保存
In [12]: Person.objects.all()
Out[12]: <QuerySet [<Person: suyn>, <Person: sophia>, <Person: HSZ>]>
## get_or_create方法:防止重复,但速度要相对慢些,返回一个元组,第一个为Person对象,第二个为True或False, 新建时返回的是True, 已经存在时返回False.
In [13]: Person.objects.get_or_create(name="LJ", age=23)
Out[13]: (<Person: LJ>, True)
In [2]: Person.objects.get_or_create(name="LJ", age=20)
Out[2]: (<Person: LJ>, True)
In [3]: Person.objects.get_or_create(name="LJ", age=20)
Out[3]: (<Person: LJ>, False)
## 获取对象的方法get/filter/exclude/all等
## 先查看数据库预览
mysql> select * from learn_person;
+----+--------+-----+
| id | name | age |
+----+--------+-----+
| 1 | suyn | 26 |
| 2 | sophia | 20 |
| 3 | HSZ | 18 |
| 4 | LJ | 23 |
| 5 | LJ | 20 |
+----+--------+-----+
5 rows in set (0.03 sec)
In [4]: Person.objects.all()
Out[4]: <QuerySet [<Person: suyn>, <Person: sophia>, <Person: HSZ>, <Person: LJ>, <Person: LJ>]>
In [5]: Person.objects.all()[:2]
Out[5]: <QuerySet [<Person: suyn>, <Person: sophia>]>
In [6]: Person.objects.filter(name="LJ") #等于
Out[6]: <QuerySet [<Person: LJ>, <Person: LJ>]>
In [7]: Person.objects.filter(name__exact="LJ") #跟name="LJ"一样
Out[7]: <QuerySet [<Person: LJ>, <Person: LJ>]>
In [8]: Person.objects.filter(name__iexact="lj") #不区分大小写
Out[8]: <QuerySet [<Person: LJ>, <Person: LJ>]>
In [9]: Person.objects.filter(name__regex="^s") #正则查询
Out[9]: <QuerySet [<Person: suyn>, <Person: sophia>]>
In [10]: Person.objects.exclude(name__regex="^s") #exclude与filter相反,排除
Out[10]: <QuerySet [<Person: HSZ>, <Person: LJ>, <Person: LJ>]>
filter的一些常用过滤条件:
__exact __iexact
__contains __icontains
__regex __iregex
由上总结QuerySet API
从数据库中查询出来的结果一般是一个集合,这个集合叫做 QuerySet。
- QuerySet创建对象的四中方法
前三种方法返回的都是对应的 object(即Author对象),最后一种方法返回的是一个元组
# 方法 1
Author.objects.create(name="WeizhongTu", email="tuweizhong@163.com")
# 方法 2
twz = Author(name="WeizhongTu", email="tuweizhong@163.com")
twz.save()
# 方法 3
twz = Author()
twz.name="WeizhongTu"
twz.email="tuweizhong@163.com"
twz.save()
# 方法 4,首先尝试获取,不存在就创建,防止重复 # 返回值(object, True/False)
Author.objects.get_or_create(name="WeizhongTu", email="tuweizhong@163.com")
- QuerySet获取对象的方法
Person.objects.all() # 查询所有
Person.objects.all()[:10] 切片操作,获取10个人,切片可以节约内存,不支持负索引(Negative indexing is not supported.)
# 解决负索引问题:
In [16]: Person.objects.order_by('id')[:2]
Out[16]: <QuerySet [<Person: suyn>, <Person: sophia>]>
In [18]: Person.objects.order_by('-id')[:2]
Out[18]: <QuerySet [<Person: LJ>, <Person: LJ>]>
Person.objects.get(name="WeizhongTu") # 名称为 WeizhongTu 的一条,多条会报错
get是用来获取一个对象的,如果需要获取满足条件的一些人,就要用到filter
Person.objects.filter(name="abc") # 等于Person.objects.filter(name__exact="abc") 名称严格等于 "abc" 的人
Person.objects.filter(name__iexact="abc") # 名称为 abc 但是不区分大小写,可以找到 ABC, Abc, aBC,这些都符合条件
Person.objects.filter(name__contains="abc") # 名称中包含 "abc"的人
Person.objects.filter(name__icontains="abc") #名称中包含 "abc",且abc不区分大小写
Person.objects.filter(name__regex="^abc") # 正则表达式查询
Person.objects.filter(name__iregex="^abc")# 正则表达式不区分大小写
# filter是找出满足条件的,当然也有排除符合某条件的
Person.objects.exclude(name__contains="WZ") # 排除包含 WZ 的Person对象
Person.objects.filter(name__contains="abc").exclude(age=23) # 找出名称含有abc, 但是排除年龄是23岁的
## 支持链式查询
Author.objects.filter(name__contains="WeizhongTu").filter(email="tuweizhong@163.com")
Author.objects.filter(name__contains="Wei").exclude(email="tuweizhong@163.com")
Person.objects.filter(name__contains="abc").exclude(age=23)
- QuerySet可迭代
In [1]: from learn.models import Entry
# 迭代Entry对象
In [10]: es = Entry.objects.all()
In [11]: for e in es:
...: print e.headline
...:
about suyn's personal blog
about lj's wonderful life
In [2]: Entry.objects.all()
Out[2]: <QuerySet [<Entry: about suyn's personal blog>, <Entry: about lj's wonderful life>]>
In [3]: Entry.objects.all().exists() #检查 Entry 中是否有对象
Out[3]: True
# 获取Entry数量
In [4]: len(Entry.objects.all())
Out[4]: 2
In [5]: Entry.objects.count() #推荐用此
Out[5]: 2
In [6]: list(Entry.objects.all()) #强行将 QuerySet 变成 列表
Out[6]: [<Entry: about suyn's personal blog>, <Entry: about lj's wonderful life>]
#查询结果排序
Author.objects.all().order_by('name')
Author.objects.all().order_by('-name') # 在 column name 前加一个负号,可以实现倒序
- QuerySet 重复的问题,使用 .distinct() 去重
一般的情况下,QuerySet 中不会出来重复的,重复是很罕见的,但是当跨越多张表进行检索后,结果并到一起,可以会出来重复的值(我最近就遇到过这样的问题)
qs1 = Pathway.objects.filter(label__name='x')
qs2 = Pathway.objects.filter(reaction__name='A + B >> C')
qs3 = Pathway.objects.filter(inputer__name='WeizhongTu')
# 合并到一起
qs = qs1 | qs2 | qs3
这个时候就有可能出现重复的
# 去重方法
qs = qs.distinct()
- QuerySet 是可以用pickle序列化到硬盘再读取出来的
>>> import pickle
>>> query = pickle.loads(s) # Assuming 's' is the pickled string.
>>> qs = MyModel.objects.all()
>>> qs.query = query # Restore the original 'query'.
数据表更改
Django 1.7.x 及以后的版本集成了 South 的功能,自动发现需要更改的,应用到数据库中去。Django 的第三方 app South 就是专门做数据库表结构自动迁移工作,它现在已经俨然成为 Django 事实上的数据库表迁移标准,很多第三方 app 都会带 South migrations 脚本。
自定义Field
-
减少文本的长度,保存数据的时候压缩,读取的时候解压缩,如果发现压缩后更长,就用原文本直接存储:
from_db_value 函数用于转化数据库中的字符到 Python的变量,
to_python 函数用于转化数据库中的字符到 Python的变量,
get_prep_value 用于将Python变量处理后(此处为压缩)保存到数据库,使用和Django自带的 Field 一样。
方法重写没有在源码中找到合适的,待修改??? -
保存一个列表到数据库中,在读取用的时候要是 Python的列表的形式,我们来自己写一个 ListField:
???不理解
网友评论