编写第一个Django应用-第二部分
这里接着第一部分开始讲,我们将创建数据库,建立一个模型,并且Django提供了自动生成的管理页面
数据库的配置
打开mysite/seting.py 几乎所有的配置都在这里面
一般情况下,默认的配置文件是sqlite作为数据库,如果你想要使用这个数据库,那么最好下载一个图形管理界面Sqliteman,就像mysql的Navicat一样,代码示例
sudo apt-get insatll sqliteman
一般开发的时候,都是选用自己熟悉的数据库,我选用的是mysql,需要更改默认配置。找到 DATABASES ‘default’ 项目中的一些键值:
您的配置文件应该如下:
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': 'Dj01', #这里是数据库的名字,需要提前创建好数据库 创建数据库的命令 "CREATE DATABASE database_name;
'USER': 'root', 数据库登录名字
'PASSWORD': 'password', 数据库登录密码
'HOST': 'localhost', 如果是本地数据库就是localhost
'PORT': '3306', 默认端口
}
}
设置 TIME_ZONE 为你自己时区。
LANGUAGE_CODE = 'zh-hans'
TIME_ZONE = 'Asia/Shanghai' #用自己地方所在的时区
Django提供的数据库API
现在让我们进入交互式 Python 命令行,尝试一下 Django 为你创建的各种 API。通过以下命令打开 Python 命令行:
API对应着相对应的数据库SQL语句,
python manage.py shell
我们使用这个命令而不是简单的使用 “Python” 是因为 manage.py 会设置 DJANGO_SETTINGS_MODULE 环境变量,这个变量会让 Django 根据 mysite/settings.py 文件来设置 Python 包的导入路径。
当你成功进入命令行后,来试试 database API 吧:
from polls.models import Choice, Question # Import the model classes we just wrote.
No questions are in the system yet.
Question.objects.all()
<QuerySet []>
Create a new Question.
Support for time zones is enabled in the default settings file, so
Django expects a datetime with tzinfo for pub_date. Use timezone.now()
instead of datetime.datetime.now() and it will do the right thing.
from django.utils import timezone
q = Question(question_text=“What’s new?”, pub_date=timezone.now())
Save the object into the database. You have to call save() explicitly.
q.save()
Now it has an ID.
q.id
1
Access model field values via Python attributes.
q.question_text
“What’s new?”q.pub_date
datetime.datetime(2012, 2, 26, 13, 0, 0, 775217, tzinfo=)
Change values by changing the attributes, then calling save().
q.question_text = “What’s up?”
q.save()
objects.all() displays all the questions in the database.
Question.objects.all()
<QuerySet [<Question: Question object (1)>]>
等等。<Question: Question object (1)> 对于我们了解这个对象的细节没什么帮助。让我们通过编辑 Question 模型的代码(位于 polls/models.py 中)来修复这个问题。给 Question 和 Choice 增加 str() 方法。
polls/models.py¶
from django.db import models
class Question(models.Model):
…
def str(self):
return self.question_text
class Choice(models.Model):
…
def str(self):
return self.choice_text
给模型增加 str() 方法是很重要的,这不仅仅能给你在命令行里使用带来方便,Django 自动生成的 admin 里也使用这个方法来表示对象。
注意:这些都是常规的 Python方法。让我们添加一个自定义的方法,这只是为了演示:
polls/models.py¶
import datetime
from django.db import models
from django.utils import timezone
class 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 工具模块。如果你不太熟悉 Python 中的时区处理,看看 时区支持文档 吧。
保存文件然后通过 python manage.py shell 命令再次打开 Python 交互式命令行:
from polls.models import Choice, Question
Make sure our str() addition worked.
Question.objects.all()
<QuerySet [<Question: What’s up?>]>
Django provides a rich database lookup API that’s entirely driven by
keyword arguments.
Question.objects.filter(id=1)
<QuerySet [<Question: What’s up?>]>Question.objects.filter(question_text__startswith=‘What’)
<QuerySet [<Question: What’s up?>]>
Get the question that was published this year.
from django.utils import timezone
current_year = timezone.now().year
Question.objects.get(pub_date__year=current_year)
<Question: What’s up?>
Request an ID that doesn’t exist, this will raise an exception.
Question.objects.get(id=2)
Traceback (most recent call last):
…
DoesNotExist: Question matching query does not exist.
Lookup by a primary key is the most common case, so Django provides a
shortcut for primary-key exact lookups.
The following is identical to Question.objects.get(id=1).
Question.objects.get(pk=1)
<Question: What’s up?>
Make sure our custom method worked.
q = Question.objects.get(pk=1)
q.was_published_recently()
True
Give the Question a couple of Choices. The create call constructs a new
Choice object, does the INSERT statement, adds the choice to the set
of available choices and returns the new Choice object. Django creates
a set to hold the “other side” of a ForeignKey relation
(e.g. a question’s choice) which can be accessed via the API.
q = Question.objects.get(pk=1)
Display any choices from the related object set – none so far.
q.choice_set.all()
<QuerySet []>
Create three choices.
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 objects have API access to their related Question objects.
c.question
<Question: What’s up?>
And vice versa: Question objects get access to Choice objects.
q.choice_set.all()
<QuerySet [<Choice: Not much>, <Choice: The sky>, <Choice: Just hacking again>]>q.choice_set.count()
3
The API automatically follows relationships as far as you need.
#Use double underscores to separate relationships.
This works as many levels deep as you want; there’s no limit.
#Find all Choices for any question whose pub_date is in this year
#(reusing the ‘current_year’ variable we created above).
Choice.objects.filter(question__pub_date__year=current_year)
<QuerySet [<Choice: Not much>, <Choice: The sky>, <Choice: Just hacking again>]>
#Let’s delete one of the choices. Use delete() for that.
c = q.choice_set.filter(choice_text__startswith=‘Just hacking’)
c.delete()
更多的关于API
阅读 访问关系对象文档可以获取关于数据库关系的更多内容。想知道关于双下划线的更多用法,参见 查找字段文档。数据库 API 的所有细节可以在数据库API文档 文档中找到
Django后台管理
python manage.py createsuperuser
输入你的用户名和密码,注意密码可能提醒你太过于简单,要求你确定是否确定创建密码:
输入 : y
可以跳过邮箱验证,
Password: **********
Password (again): *********
Superuser created successfully.
现在,打开浏览器,转到你本地域名的 “/admin/” 目录, – 比如 “http://127.0.0.1:8000/admin/” 。你应该会看见管理员登录界面,
向管理页面加入投票页面
我们得告诉管理页面,问题 Question 对象需要被管理。打开 polls/admin.py 文件,把它编辑成下面这样:
from django.contrib import admin
from .models import Question
admin.site.register(Question)
现在你就可以便捷的管理了
点击 “Questions” 。现在看到是问题 “Questions” 对象的列表 “change list” 。这个界面会显示所有数据库里的问题 Question 对象,你可以选择一个来修改。这里现在有我们在上一部分中创建的 “What’s up?” 问题
页面的底部提供了几个选项:
保存(Save) - 保存改变,然后返回对象列表。
保存并继续编辑(Save and continue editing) - 保存改变,然后重新载入当前对象的修改界面。
保存并新增(Save and add another) - 保存改变,然后添加一个新的空对象并载入修改界面。
删除(Delete) - 显示一个确认删除页面
注意
在添加新的问题时,可能会遇到问题,当你添加中文问题时,可能会报错。对于错误"
Incorrect string value: '\xE6\xA2\xB5\xE8\x92\x82…'for column ‘object_repr’ at row 1
解决方法是设置django_admin_log表的object_repr一项使用utf8_unicode_ci;
对于错误" Incorrect string value: '\xE6\xA2\xB5\xE8\x92\x82…'for column ‘change_message’ at row 1 “
解决方法是设置django_admin_log表的change_message一项使用utf8_unicode_ci;
具体mysql语句为:mysql> ALTER TABLE django_admin_log MODIFY COLUMN object_repr VARCHAR(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL;
mysql > ALTER TABLE django_admin_log MODIFY COLUMN change_message VARCHAR(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL;
如果还不行,那么就去用你们的图形化管理工具将mysql的数据库,数据表,字段的编码都设置为utf8。
最后重点
重点在于数据库API的运用,可以去看官方文档,在前面已经贴了链接。
如果出了什么不为人知的问题,我的建议是:谷歌大法。百度出来的都是一样的,没有实质性的。