1. Bare-bones model
This is a basic model with only two non-primary-key fields.
每创建一个app,都需要执行manage.py startapp app_name命令,
这样manage.py会在当前目录下面建立app_name目录并且创建几个
必须的文件。
如下命令:
$ls -l bare_bones
ls: bare_bones: No such file or directory
$manage.py startapp bare_bones
$ls -l bare_bones
total 2
-rw-rw-rw- 1 user group 0 Jun 26 10:49 __init__.py
-rw-rw-rw- 1 user group 60 Jun 26 10:49 models.py
-rw-rw-rw- 1 user group 27 Jun 26 10:49 views.py
OK,修改一下models.py,以开始model之旅。
from django.db import models
# Create your models here.
class Article(models.Model):
headline = models.CharField(maxlength=100, default='Default headline')
pub_date = models.DateTimeField()
def __str__(self):
return self.headline
$manage.py syncdb
??为什么没有响应嗯?哦哦,我搞忘了往INSTALLED_APPS里面加入这个新的app了。
打开settings.py找到INSTALLED_APPS把bare_bones添加进去
$manage.py syncdb
Creating table bare_bones_article
Adding content type 'bare_bones | article'
好了,现在开始练习Django的model API了!
准备进入django的shell世界:
$manage.py shell
Python 2.4.3 (#69, Mar 29 2006, 17:35:34)
Type "help", "copyright", "credits" or "license" for more information.
(InteractiveConsole)
>>>
Sample API usage
Article在bare_bones/models.py中. 所以:
>>> from bare_bones.models import Article
# 看看系统中现在有多少文章
>>> Article.objects.all()
[]
# 哦,一个都没有
# 那创建一个先:
>>> from datetime import datetime
>>> a = Article(id=None, headline='Area man programs in Python', pub_date=datetime(2005, 7, 28))
# 创建了,还没有保存呢!现在数据库里面还是空的,通过调用save()来保存它到数据库.
>>> a.save()
# 现在可以用数据库工具,看看数据库里面的bare_bones_articl表,会多出一条记录的。
# 同时a会多出一个id的属性,后面跟个"L",表示这是一个长整型。这个id属性在保存到数据库之前是空的
# 在保存到数据库之后会自动根据数据库的记录,自动映射到id。
>>> a.id
1L
# 现在可以使用实例的属性来访问数据表的列了:
>>> a.headline
'Area man programs in Python'
>>> a.pub_date
datetime.datetime(2005, 7, 28, 0, 0)
# 当然也可以改变实例的属性,然后调用save()来修改数据库里面的记录
>>> a.headline = 'Area woman programs in Python'
>>> a.save()
>>> a.id
1L
# 果然只是headline列的数据发生变化,而id并没有变化
# 还可以通过Article.objects.all()来列出数据库中所以的文章,这是一个类的方法,而不是一个实例的操作.
>>> Article.objects.all()
[<Article: Area woman programs in Python>]
# 同时Django还提供了丰富的查找API,
# 这些API的作用相当于select中的where子句,
# 但是却看不到一个where的影子
# 比如id__exact=1 表示id等于1的文章
>>> Article.objects.get(id__exact=1)
<Article: Area woman programs in Python>
# 而这个headline__startswith='Area woman'则是说headline这一列以'Area woman'
# 打头的
>>> Article.objects.get(headline__startswith='Area woman')
<Article: Area woman programs in Python>
# 请留意一下接下来的几个列的类型为日期时可以使用的参数,
# 可以对照一下,如果直接在sql语句中使用这些日期方面的函数会是什么样子呢?
# ^_^,Django已经考虑了很多,做了很多了!
>>> Article.objects.get(pub_date__year=2005)
<Article: Area woman programs in Python>
>>> Article.objects.get(pub_date__year=2005, pub_date__month=7)
<Article: Area woman programs in Python>
>>> Article.objects.get(pub_date__year=2005, pub_date__month=7, pub_date__day=28)
<Article: Area woman programs in Python>
# 其实"__exact"是可以省略的.
>>> Article.objects.get(id=1)
<Article: Area woman programs in Python>
>>> Article.objects.get(headline='Area woman programs in Python')
<Article: Area woman programs in Python>
>>> Article.objects.filter(pub_date__year=2005)
[<Article: Area woman programs in Python>]
>>> Article.objects.filter(pub_date__year=2004)
[]
>>> Article.objects.filter(pub_date__year=2005, pub_date__month=7)
[<Article: Area woman programs in Python>]
# 找不到对象,会有什么事情发生呢?
# 当get()参数在数据库中没有找到匹配的记录的时候,Django会抛出DoesNotExist异常
>>> Article.objects.get(id__exact=2)
Traceback (most recent call last):
...
DoesNotExist: Article matching query does not exist.
>>> Article.objects.get(pub_date__year=2005, pub_date__month=8)
Traceback (most recent call last):
...
DoesNotExist: Article matching query does not exist.
# 其实最常用的是针对主键进行的查找,所以Django的get函数还有pk这样一个参数:
# The following is identical to articles.get(id=1).
>>> Article.objects.get(pk=1)
<Article: Area woman programs in Python>
# Model instances of the same type and same ID are considered equal.
>>> a = Article.objects.get(pk=1)
>>> b = Article.objects.get(pk=1)
>>> a == b
True
# 也可以使用不同的风格来初始化一个实例
>>> a2 = Article(None, 'Second article', datetime(2005, 7, 29))
>>> a2.save()
>>> a2.id
2L
>>> a2.headline
'Second article'
>>> a2.pub_date
datetime.datetime(2005, 7, 29, 0, 0)
# 这种风格也是没有问题的
>>> a3 = Article(id=None, headline='Third article', pub_date=datetime(2005, 7, 30))
>>> a3.save()
>>> a3.id
3L
>>> a3.headline
'Third article'
>>> a3.pub_date
datetime.datetime(2005, 7, 30, 0, 0)
# 两种风格的综合
>>> a4 = Article(None, 'Fourth article', pub_date=datetime(2005, 7, 31))
>>> a4.save()
>>> a4.headline
'Fourth article'
# 不要传入错误的实参
>>> a5 = Article(id=None, headline='Invalid', pub_date=datetime(2005, 7, 31), foo='bar')
Traceback (most recent call last):
...
TypeError: 'foo' is an invalid keyword argument for this function
# 对于类型为AutoField的列,可以为空,当使用save()保存到数据库里面的时候,会自动
# 填充的
>>> a5 = Article(headline='Article 6', pub_date=datetime(2005, 7, 31))
>>> a5.save()
>>> a5.id
5L
>>> a5.headline
'Article 6'
# 对于有default属性的列,也可以为空,这样Django会使用它的默认值
>>> a6 = Article(pub_date=datetime(2005, 7, 31))
>>> a6.save()
>>> a6.headline
'Default headline'
# 对于 DateTimeFields类型的列, Django以精确度为秒来保存
>>> a7 = Article(headline='Article 7', pub_date=datetime(2005, 7, 31, 12, 30))
>>> a7.save()
>>> Article.objects.get(id__exact=7).pub_date
datetime.datetime(2005, 7, 31, 12, 30)
>>> a8 = Article(headline='Article 8', pub_date=datetime(2005, 7, 31, 12, 30, 45))
>>> a8.save()
>>> Article.objects.get(id__exact=8).pub_date
datetime.datetime(2005, 7, 31, 12, 30, 45)
>>> a8.id
8L
# 重复保存一个对象,并不会在数据库中创建新的记录,而只是保存或者更新老的记录
>>> a8.save()
>>> a8.id
8L
>>> a8.headline = 'Updated article 8'
>>> a8.save()
>>> a8.id
8L
>>> a7 == a8
False
>>> a8 == Article.objects.get(id__exact=8)
True
>>> a7 != a8
True
>>> Article.objects.get(id__exact=8) != Article.objects.get(id__exact=7)
True
>>> Article.objects.get(id__exact=8) == Article.objects.get(id__exact=7)
False
# dates() 会根据参数返回数据库中指定列的可用日期的一个list.
>>> Article.objects.dates('pub_date', 'year')
[datetime.datetime(2005, 1, 1, 0, 0)]
>>> Article.objects.dates('pub_date', 'month')
[datetime.datetime(2005, 7, 1, 0, 0)]
>>> Article.objects.dates('pub_date', 'day')
[datetime.datetime(2005, 7, 28, 0, 0), datetime.datetime(2005, 7, 29, 0, 0), datetime.datetime(2005, 7, 30, 0, 0), datetime.datetime(2005, 7, 31, 0, 0)]
# 对于返回的多个结果可以使用order='ASC'或者order='DESC'参数(ASC或者DESC是大小写敏感的)来排序
>>> Article.objects.dates('pub_date', 'day', order='ASC')
[datetime.datetime(2005, 7, 28, 0, 0), datetime.datetime(2005, 7, 29, 0, 0), datetime.datetime(2005, 7, 30, 0, 0), datetime.datetime(2005, 7, 31, 0, 0)]
>>> Article.objects.dates('pub_date', 'day', order='DESC')
[datetime.datetime(2005, 7, 31, 0, 0), datetime.datetime(2005, 7, 30, 0, 0), datetime.datetime(2005, 7, 29, 0, 0), datetime.datetime(2005, 7, 28, 0, 0)]
# dates() 的参数要求:
>>> Article.objects.dates()
Traceback (most recent call last):
...
TypeError: dates() takes at least 3 arguments (1 given)
>>> Article.objects.dates('invalid_field', 'year')
Traceback (most recent call last):
...
FieldDoesNotExist: Article has no field named 'invalid_field'
>>> Article.objects.dates('pub_date', 'bad_kind')
Traceback (most recent call last):
...
AssertionError: 'kind' must be one of 'year', 'month' or 'day'.
>>> Article.objects.dates('pub_date', 'year', order='bad order')
Traceback (most recent call last):
...
AssertionError: 'order' must be either 'ASC' or 'DESC'.
# 要在循环中使用dates()可以使用iterator()来遍历,iterator()每次只返回一个结果
>>> for a in Article.objects.dates('pub_date', 'day', order='DESC').iterator():
... print repr(a)
datetime.datetime(2005, 7, 31, 0, 0)
datetime.datetime(2005, 7, 30, 0, 0)
datetime.datetime(2005, 7, 29, 0, 0)
datetime.datetime(2005, 7, 28, 0, 0)
# 也可以使用"|" 和"&"来合并查询,相当于select中的"OR"和"AND"子句
>>> s1 = Article.objects.filter(id__exact=1)
>>> s2 = Article.objects.filter(id__exact=2)
>>> s1 | s2
[<Article: Area woman programs in Python>, <Article: Second article>]
>>> s1 & s2
[]
# 想得到对象的数目?可以这样做:
>>> len(Article.objects.filter(id__exact=1))
1
# 索引和切片操作也是可以的:
>>> Article.objects.all()[0]
<Article: Area woman programs in Python>
>>> Article.objects.all()[1:3]
[<Article: Second article>, <Article: Third article>]
>>> s3 = Article.objects.filter(id__exact=3)
>>> (s1 | s2 | s3)[::2]
[<Article: Area woman programs in Python>, <Article: Third article>]
>>> Article.objects.all()[0:5].filter()
[<Article: Area woman programs in Python>, <Article: Second article>, <Article: Third article>, <Article: Fourth article>, <Article: Article 6>]
>>> Article.objects.all()[0:5][0:2]
[<Article: Area woman programs in Python>, <Article: Second article>]
>>> Article.objects.all()[0:5][:2]
[<Article: Area woman programs in Python>, <Article: Second article>]
>>> Article.objects.all()[0:5][4:]
[<Article: Article 6>]
>>> Article.objects.all()[0:5][5:]
[]
# 一些其它的测试
>>> Article.objects.all()[2:][0:2]
[<Article: Third article>, <Article: Fourth article>]
>>> Article.objects.all()[2:][:2]
[<Article: Third article>, <Article: Fourth article>]
>>> Article.objects.all()[2:][2:3]
[<Article: Article 6>]
# 对于一些数据库,在没有limit的时候不能使用offset,
>>> Article.objects.all()[2:]
Traceback (most recent call last):
...
AssertionError: 'offset' is not allowed without 'limit'
# 而且一旦切片之后,就不能再执行过滤、排序、以及合并
>>> Article.objects.all()[0:5].filter(id=1)
Traceback (most recent call last):
...
AssertionError: Cannot filter a query once a slice has been taken.
>>> Article.objects.all()[0:5].order_by('id')
Traceback (most recent call last):
...
AssertionError: Cannot reorder a query once a slice has been taken.
>>> Article.objects.all()[0:1] & Article.objects.all()[4:5]
Traceback (most recent call last):
...
AssertionError: Cannot combine queries once a slice has been taken.
# 由于数据库限制,不支持负的切片操作
# (hint: inverting your ordering might do what you need).
>>> Article.objects.all()[-1]
Traceback (most recent call last):
...
AssertionError: Negative indexing is not supported.
>>> Article.objects.all()[0:-5]
Traceback (most recent call last):
...
AssertionError: Negative indexing is not supported.
# 实例是没有"objects"属性的,该属性是属于类的属性
>>> a7.objects.all()
Traceback (most recent call last):
...
AttributeError: Manager isn't accessible via Article instances
>>> a7.objects
Traceback (most recent call last):
...
AttributeError: Manager isn't accessible via Article instances
# 批量删除记录:
>>> Article.objects.all()
[<Article: Area woman programs in Python>, <Article: Second article>, <Article: Third article>, <Article: Fourth article>, <Article: Article 6>, <Article: Default headline>, <Article: Article 7>, <Article: Updated article 8>]
>>> Article.objects.filter(id__lte=4).delete()
>>> Article.objects.all()
[<Article: Article 6>, <Article: Default headline>, <Article: Article 7>, <Article: Updated article 8>]
# 在PostgreSQL中, 时间精度可以达到微秒级别
>>> a9 = Article(headline='Article 9', pub_date=datetime(2005, 7, 31, 12, 30, 45, 180))
>>> a9.save()
>>> Article.objects.get(id__exact=9).pub_date
datetime.datetime(2005, 7, 31, 12, 30, 45, 180)
# 在MySQL中则不行,会丢失微秒级别的时间
>>> a9 = Article(headline='Article 9', pub_date=datetime(2005, 7, 31, 12, 30, 45, 180))
>>> a9.save()
>>> Article.objects.get(id__exact=9).pub_date
datetime.datetime(2005, 7, 31, 12, 30, 45)
# 创建对象的时候也可以手动指定主键值:
>>> a101 = Article(id=101, headline='Article 101', pub_date=datetime(2005, 7, 31, 12, 30, 45))
>>> a101.save()
>>> a101 = Article.objects.get(pk=101)
>>> a101.headline
'Article 101'