Django基础(三):models-database

2017-10-17  本文已影响15人  宇辰星君

[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。

  1. 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")
  1. 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)
  1. 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 前加一个负号,可以实现倒序
  1. 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()
  1. 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

上一篇下一篇

猜你喜欢

热点阅读