首页 > 代码库 > Django1.7学习(二)

Django1.7学习(二)

7.玩转API

接下来,我们进入 Python 的交互式 shell 中玩转 Django 提供的 API 。使用以下命令调用Python shell:

python manage.py shell

我们当前使用的环境不同于简单的输入 “python” 进入的 shell 环境, manage.py 文件设置了 DJANGO_SETTINGS_MODULE环境变量,该变量给定了 Django 需要导入的 mysite/settings.py 文件所在路径。

注:如果确实不想使用 manage.py 也可以,只需要设置环境变量DJANGO_SETTINGS_MODULE的值为mysite.settings,启用Python shell 并输入以下命令即可:

import djangodjango.setup()

此处需注意应在与 manage.py 文件所在同一目录下运行 python ( 或确保目录在 Python path 下)

进入shell中后,就可以开始探索 database API了

>>> from polls.models import Question, Choice   # 导入刚创建的模块类>>> Question.objects.all()[]# 创建一个新的Question# 默认配置文件中时区支持是启用的,因此 Django 希望为 pub_date 获取一个带 tzinfo 的 datetime# 此处使用 timezone.now() 来替代 datetime.datetime.now() 以获取正确的值>>> from django.utils import timezone>>> q = Question(question_text="What‘s new?",pub_date=timezone.now())# 将对象保存到数据库中,此处应调用save() 方法>>> q.save()# 现在对象有了一个 ID. 此处注意有可能会显示 "1L" 而不是 "1", 这取决于你正使用的数据库# 这无关紧要,仅仅表明你的数据库后端更偏向于返回 integers 作为 Python 的 long integer 对象>>> q.id1# 通过 Python 属性访问字段值>>> q.question_text"What‘s new?">>> q.pub_datedatetime.datetime(2012, 2, 26, 13, 0, 0, 775217, tzinfo=<UTC>)# 通过改变属性来改变值, 然后调用 save().>>> q.question_text = "What‘s up?">>> q.save()# objects.all() 用以打印出所有在数据库中的 question.>>> Question.objects.all()[<Question: Question object>]

注意:<Question: Question object> 这样的对象显示方式是毫无意义的。

为了转换成我们看得懂的显示方式,此处可以通过修改 Question 这个model (polls/models.py 文件中)并为 Question 和 Choice 都添加上一个__str__()方法:

from django.db import modelsclass Question(models.Model):    # ...    def __str__(self):              #Python 2.x 用 __unicode__         return self.question_textclass Choice(models.Model):    # ...    def __str__(self):              #Python 2.x 用 __unicode__        return self.choice_text

为 models 添加__str__()方法是很重要的,不只能让自己在处理交互式提示时更加清晰,同时在 Django 自动生成的后台管理界面中也会用到

__str__ 还是 __unicode__?

如果使用的是Python 3.x 版本,很简单,直接使用 __str__()

如果使用的是Python 2.x 版本,则需要定义 __unicode__()方法来返回unicode值。Django 的 models 有一个默认的__str__()方法会调用__unicode__()方法将结果转换成UTF-8编码的字符串,这就意味着 unicode(p)将返回一个Unicode编码的字符串,而str(p)将返回一个UTF-8编码字符串。Python则相反:object 拥有一个__unicode__ 方法调用__str__将结果转变为 ASCII 字符串,这极容易造成混淆。

如果上面的这些让你感觉到混乱,那么推荐使用Python 3.x版本。

 接下来尝试着自定义一个方法

import datetimefrom django.db import modelsfrom django.utils import timezoneclass Question(models.Model):    # ...    def was_published_recently(self):        return self.pub_date >= timezone.now() - datetime.timedelta(days=1)

增加了 import datetime 和 from django.utils import timezone, 分别是为了引用 Python 的标准库的 datetime 模块和 Django 的 django.utils.timezone 中的 time-zone-related 实用工具 。

保存以上更改并且再次运行 python manage.py shell 以开启一个新的 Python shel>>> from polls.models import Question, Choice

# 确认下添加的 __str__() 正常运行.>>> Question.objects.all()[<Question: Whats up?>]# Django 提供了一个丰富的完全由关键字驱动的数据库查询 API >>> Question.objects.filter(id=1)[<Question: Whats up?>]>>> Question.objects.filter(question_text__startswith=What)[<Question: Whats up?>]# 获取在今年内发布的 Question>>> from django.utils import timezone>>> current_year = timezone.now().year>>> Question.objects.get(pub_date__year=current_year)<Question: Whats up?># 请求一个不存在的 ID ,然后将引发异常.>>> Question.objects.get(id=2)Traceback (most recent call last):    ...DoesNotExist: Question matching query does not exist.# 根据主键查询是一种比较常见的方式, 因此 Django 提供了一个精确查找主键的快捷方式# 以下内容等同于 Question.objects.get(id=1).>>> Question.objects.get(pk=1)<Question: Whats up?># 确认下我们自定义的方法正常运行.>>> q = Question.objects.get(pk=1)>>> q.was_published_recently()True# 给 Question 设置一些 Choice. 创建一个新的 Choice 对象,执行 INSERT 语句后, 
# 添加 choice 到可用的 choices 集合然后
返回一个新的 Choice 对象.
# Django 创建了一个可以通过 API 访问的保存外键关联的集合(如 question 的 choice)
>>> q = Question.objects.get(pk=1)# 从关联对象集合中显示所有 choice -- 当前为空.>>> q.choice_set.all()[]# 创建三个 choice.>>> q.choice_set.create(choice_text=Not much, votes=0)<Choice: Not much>>>> q.choice_set.create(choice_text=The sky, votes=0)<Choice: The sky>>>> c = q.choice_set.create(choice_text=Just hacking again, votes=0)# Choice 对象拥有访问与它们关联的 Question 对象的 API>>> c.question<Question: Whats up?># 反之亦然: Question 对象也可以访问 Choice 对象.>>> q.choice_set.all()[<Choice: Not much>, <Choice: The sky>, <Choice: Just hacking again>]>>> q.choice_set.count()3# 只要需要 API 会自动连续关联可以使用双下划线来隔离关联
# 需要多少层的关联就可以有多少层的关联
,没有任何限制# 找出所有 pub_date 在今年的与 question 有关联的 Choice# (重复使用我们之前创建的的变量 ‘current_year‘)>>> Choice.objects.filter(question__pub_date__year=current_year)[<Choice: Not much>, <Choice: The sky>, <Choice: Just hacking again>]# 用 delete() 来删除 choices 的其中一个.>>> c = q.choice_set.filter(choice_text__startswith=Just hacking)>>> c.delete()

 参考:https://docs.djangoproject.com/en/1.7/intro/tutorial01/

未完待续。。。

Django1.7学习(二)