玩转模型层的API
现在,让我们进入Python shell中玩转Django为我们提供了的免费的API。使用下面的命令运行Python shell:
python manage.py shell
现在你已经进入到shell中了,研究一下这些数据库的API吧:
Code
>>> from mysite.polls.models import Poll, Choice # Import the model classes we just wrote.
# 现在系统中还没有polls。
>>> Poll.objects.all()
[]
# 创建一个新的Poll。
>>> import datetime
>>> p = Poll(question="What's up?", pub_date=datetime.datetime.now())
# 把这个对象保存到数据库中。你需要显式调用save()方法。
>>> p.save()
# 现在它有一个ID了。它有可能是"1L"或者"1",
# 这完全取决于你正在使用的数据库。这不是什么大问题;
# 它只不过是返回一个Python长整型对象的数字而已。
>>> p.id
1
# 通过Python的属性值访问数据库的列。
>>> p.question
"What's up?"
>>> p.pub_date
datetime.datetime(2007, 7, 15, 12, 00, 53)
# 通过Python属性值修改数据库的值,并调用save()方法。
>>> p.pub_date = datetime.datetime(2007, 4, 1, 0, 0)
>>> p.save()
# objects.all()显示数据库中所有的polls。
>>> Poll.objects.all()
[<Poll: Poll object>]
等下。<Poll: Poll object> 根本就不能帮助我们描述这个对象。让我们编辑polls模型来修正它(在polls/models.py文件中),给Poll和Choice方法各添加一个__unicode__()方法。
class Poll(models.Model):
#
def __unicode__(self):
return self.question
class Choice(models.Model):
#
def __unicode__(self):
return self.choice
如果__unicode__()看起来没有执行
如果你给你的models添加的__unicode__()方法并没有看到它们的描述信息有变化,你很可能正在使用的是旧版本的Django。(本教程是面向Django最新的开发版写的。)旧版使用__str__()方法。
给你的models添加__unicode__()方法是件很重要的事情,它不仅仅是为了使你在提示窗口中得到智能的提示,更是因为对象的描述在Django自动生成的admin中会使用到。
为什么是__unicode__()而不是django.db.models.Model.__str__()?
如 果你熟悉Python的话,你可能习惯于给你的类添加django.db.models.Model.__str__()方法而不是 __unicode__()方法。我们这里之所以使用__unicode__()是因为Django models默认是处理Unicode的。所有保存在你的数据库中的数据在返回的时候都转换为Unicode。
Django models有一个默认的方法django.db.models.Model.__str__(),它会调用__unicode__()方法并返回一个 UTF-8格式的字符串。也就是说,unicode(p)将会返回一个Unicode的字符串,而str(p)将会返回一个普通的字符串,它的字符是被编 码为UTF-8的。
如果你还不理解的话,你只要记得给你的models添加__unicode__()方法就行了。如果运气不背的话,事情就会如你所愿的执行。
注意下面这些普通的Python方法。让我们添加一些自定义的方法,就如例子所演示的:
import datetime
#
class Poll(models.Model):
#
def was_published_today(self):
return self.pub_date.date() == datetime.date.today()
注意到,我添加了import datetime来引用Python的标准datetime模块。
让我们再次运行python manage.py shell来进入Python shell吧:
Code
>>> from mysite.polls.models import Poll, Choice
# 确认我们添加的__unicode__()方法能够正确执行
>>> Poll.objects.all()
[<Poll: What's up?>]
# Django 提供了丰富的数据库检索API,它完全是使用关键字参数运行。
>>> Poll.objects.filter(id=1)
[<Poll: What's up?>]
>>> Poll.objects.filter(question__startswith='What')
[<Poll: What's up?>]
# 返回年份是2007年的poll。当然了,你也可以检索其它年份,
# 只需要做适当的修改。
>>> Poll.objects.get(pub_date__year=2007)
<Poll: What's up?>
>>> Poll.objects.get(id=2)
Traceback (most recent call last):
DoesNotExist: Poll matching query does not exist.
# 根据主键检索是最常用的, 因此Django提供了更便捷的
# 使用主键检索的方法。
# 下面的语句和Poll.objects.get(id=1)是等效的。
>>> Poll.objects.get(pk=1)
<Poll: What's up?>
# 确认我们自定义的方法是否能执行
>>> p = Poll.objects.get(pk=1)
>>> p.was_published_today()
False
# 给Poll更多的选择。create方法构建一个新的choice对象,
# 执行Insert命令, 把choice添加到变量choices中,
# 返回这个新创建的Choice对象。
>>> p = Poll.objects.get(pk=1)
>>> p.choice_set.create(choice='Not much', votes=0)
<Choice: Not much>
>>> p.choice_set.create(choice='The sky', votes=0)
<Choice: The sky>
>>> c = p.choice_set.create(choice='Just hacking again', votes=0)
# Choice对象拥有访问它们关联的Poll对象的API。
>>> c.poll
<Poll: What's up?>
# 反之亦然:Poll对象能够访问Choice对象。
>>> p.choice_set.all()
[<Choice: Not much>, <Choice: The sky>, <Choice: Just hacking again>]
>>> p.choice_set.count()
3
# 这些API是在你需要使用的时候自动关联的。
# 使用两个下划线来分开关联
# 它能作用到不同的层面;它是没有限制的。
# 检索所有的Choices的所有pub_date是在2007年的poll。
>>> Choice.objects.filter(poll__pub_date__year=2007)
[<Choice: Not much>, <Choice: The sky>, <Choice: Just hacking again>]
# 让我们删除所有的choices。使用delete()方法来完成它。
>>> c = p.choice_set.filter(choice__startswith='Just hacking')
>>> c.delete()
如果还有读者还不熟悉Python和Django的安装,请阅读我写的一篇关于这方面的教程: