学习Django的官方教程时记录的笔记
Writing your first Django app, part 1
1.1 Basic command
python -m django --version
查询当前django版本django-admin startproject mysite
在当前目录下创建一个Django应用note: You’ll need to avoid naming projects after built-in Python or Django components. In particular, this means you should avoid using names like
django
(which will conflict with Django itself) ortest
(which conflicts with a built-in Python package).Automatic reloading of
runserver
The development server automatically reloads Python code for each request as needed. You don’t need to restart the server for code changes to take effect. However, some actions like adding files don’t trigger a restart, so you’ll have to restart the server in these cases.
Projects vs. apps
What’s the difference between a project and an app? An app is a Web application that does something – e.g., a Weblog system, a database of public records or a simple poll app. A project is a collection of configuration and apps for a particular website. A project can contain multiple apps. An app can be in multiple projects.
通过
$ python manage.py startapp polls
指令,创建一个名称为polls的web app
1.2 URLconfs
下面以mysite/mysite/urls.py
中的URLconfs对其结构进行说明
1 | urlpatterns = [ |
The
include()
function allows referencing other URLconfs. Whenever Django encountersinclude()
, it chops off whatever part of the URL matched up to that point and sends the remaining string to the included URLconf for further processing.When to use
include()
You should always use
include()
when you include other URL patterns.admin.site.urls
is the only exception to this.也就是说,在需要从
urls.py
指向另外一个应用中的urls.py
时,需要使用include来指向另外一个页面的URLconfsThe
path()
function is passed four arguments, two required:route
andview
, and two optional:kwargs
, andname
.route
is a string that contains a URL pattern. When processing a request, Django starts at the first pattern inurlpatterns
and makes its way down the list, comparing the requested URL against each pattern until it finds one that matches.- When Django finds a matching pattern, it calls the specified view function with an
HttpRequest
object as the first argument and any “captured” values from the route as keyword arguments. - Arbitrary keyword arguments can be passed in a dictionary to the target view
- Naming your URL lets you refer to it unambiguously from elsewhere in Django, especially from within templates. This powerful feature allows you to make global changes to the URL patterns of your project while only touching a single file.
Writing your first Django app, part 2
Model
Now we’ll define your models – essentially, your database layout, with additional metadata.
A model is the single, definitive source of truth about your data. It contains the essential fields and behaviors of the data you’re storing. Django follows the DRY Principle. The goal is to define your data model in one place and automatically derive things from it.
Install App
That small bit of model code gives Django a lot of information. With it, Django is able to:
- Create a database schema (
CREATE TABLE
statements) for this app. - Create a Python database-access API for accessing
Question
andChoice
objects.
But first we need to tell our project that the polls
app is installed.
To include the app in our project, we need to add a reference to its configuration class in the INSTALLED_APPS
setting.
$ python manage.py makemigrations polls
Migrations are how Django stores changes to your models (and thus your database schema) - they’re just files on disk. You can read the migration for your new model if you like; it’s the file polls/migrations/0001_initial.py
. Don’t worry, you’re not expected to read them every time Django makes one, but they’re designed to be human-editable in case you want to manually tweak how Django changes things.
自动生成的辅助文件可以让我们对生成的数据库有一个更加直观的理解,并且通过指令python manage.py sqlmigrate polls 0001
,可以解读等价的SQL指令
The
sqlmigrate
command doesn’t actually run the migration on your database - it just prints it to the screen so that you can see what SQL Django thinks is required. It’s useful for checking what Django is going to do or if you have database administrators who require SQL scripts for changes.
在安装过app之后,需要进行迁移以创建相应的数据库,这是增量进行的,并不是每次重新创建全部的数据库
python manage.py migrate
值得注意的是,在我使用DB Browers打开数据库的时候,是没有办法对该数据库文件更新的,提示的错误信息是
django.db.utils.OperationalError: database is locked
这说明在我打开数据库的时候,它是锁定的,没有办法进行写操作
The Whole Procedure
Migrations are very powerful and let you change your models over time, as you develop your project, without the need to delete your database or tables and make new ones - it specializes in upgrading your database live, without losing data. We’ll cover them in more depth in a later part of the tutorial, but for now, remember the three-step guide to making model changes:
- Change your models (in
models.py
). - Run
python manage.py makemigrations
to create migrations for those changes - Run
python manage.py migrate
to apply those changes to the database.
The reason that there are separate commands to make and apply migrations is because you’ll commit migrations to your version control system and ship them with your app; they not only make your development easier, they’re also usable by other developers and in production.
How to create one super user
python manage.py createsuperuser
Make the poll app modifiable in the admin¶
But where’s our poll app? It’s not displayed on the admin index page.
Just one thing to do: we need to tell the admin that Question
objects have an admin interface. To do this, open the polls/admin.py
file, and edit it to look like this:
1 | from django.contrib import admin |
Writing your first Django app, part 3
Writing more views
通过搭配views.py
& urls.py
,我进一步对urlpatterns的作用有了清楚的认识
在views中通过定义函数,表明在该目录polls下将会存在哪些子目录,并且规定其中的显示内容
之后在urls中规定什么样的url将会激发什么样的views,甚至可以通过规定url中的格式来向其中传参
Write views that actually do something
尽管上述通过views的方法定义了一些静态页面,但是它们的作用不是很大,django引入了自己的一套html框架,其中使用中括号作为一种自动化的措施,该框架大致如下
但是也可能是因为自己对html还没有掌握好,因此尚未深入到这样的程度
并且,上面的html模板定义的位置还有一个讲究,上述index.html
文件,需要定义在polls/templates/polls/
文件夹下面,这是为了避免出现查找模板的时候遭遇冲突
Template namespacing
Now we might be able to get away with putting our templates directly in
polls/templates
(rather than creating anotherpolls
subdirectory), but it would actually be a bad idea. Django will choose the first template it finds whose name matches, and if you had a template with the same name in a different application, Django would be unable to distinguish between them. We need to be able to point Django at the right one, and the easiest way to ensure this is by namespacing them. That is, by putting those templates inside another directory named for the application itself.
同时,为了调用这个模板,需要在polls/view.py
文件中定义这样的index()
方法
1 | from django.http import HttpResponse |
render(context=None, request=None)
方法通过context参数传入html模板里面将会出现的各种参数,而request属性是由目前的http请求得到的
同时,该render还有另外的一个简便版本
1 | from django.shortcuts import render |
虽然上面的render方法的设计只是为了简化操作,但是类似的方法get_object_or_404()
则起到了解耦的作用
Philosophy
Why do we use a helper function
get_object_or_404()
instead of automatically catching theObjectDoesNotExist
exceptions at a higher level, or having the model API raiseHttp404
instead ofObjectDoesNotExist
?Because that would couple the model layer to the view layer. One of the foremost design goals of Django is to maintain loose coupling. Some controlled coupling is introduced in the
django.shortcuts
module.
Writing your first Django app, part 4
这一部分通过新建两个html文件detail.html
& results.html
;建立一个通过vote更新数据的函数,使得poll应用已经能够正常使用了,下面依次记录我对它们的理解
detail.html
内部结构
该页面用于进行投票,所以必须有一个数据的转移
具体的实现放在了form标签的action属性中,需要注意的是,action中的内容使用了解耦的方式来编写,前面的url
的内容,与urls.py
文件中对应项的内容一致,后面的内容目前还不了解。
软编码
在part 3的最后一部分,学习了一下软编码的使用方法。所谓的软编码,就是通过向上搜索urls.py
中定义的url路径,来填充html中的相应url。具体的使用方法为url url_name
,其中url_name
出现在urlpatterns
中path
方法的第二个参数,如果这条url中存在变量,那么其格式将是url url_name variable_name
另外一个需要注意的点,是URL的命名空间。也就是在指定url_name
的时候,必须加上对应的前缀。
与软编码使用方式相同的还有django.urls
包中的reverse()
函数,用于给定url_name
,返回对应的url。需要注意的是,如果其中含有变量,那么需要第二个参数来指定变量
调用过程
当在浏览器中输入localhost:8000/polls/1
的时候,这条url匹配到了位于polls/urls.py
中urlpatterns
中的第三条路径,根据其中的参数,将会在views.py
中寻找DetailView
的实现
根据其中指定的template_name
,将会调用位于template/polls/detail.html
的模板
views.py
内部结构
1 | from django.shortcuts import render |
调用工程
从detail.html
中首先读取目前已经submit的选项,如果没有选择,发出错误信息;如果读取到了选择的结果,那么更新成员变量,并且返回一个reuslts.html
视图
Writing your first Django app, part 5
本节介绍了Django的测试框架
相对于Python的原生测试框架,十分易用,也因此屏蔽了更多的底层内容
调用过程
What happened is this:
manage.py test polls
looked for tests in thepolls
application- it found a subclass of the
django.test.TestCase
class - it created a special database for the purpose of testing
- it looked for test methods - ones whose names begin with
test
- in
test_was_published_recently_with_future_question
it created aQuestion
instance whosepub_date
field is 30 days in the future - … and using the
assertIs()
method, it discovered that itswas_published_recently()
returnsTrue
, though we wanted it to returnFalse
The test informs us which test failed and even the line on which the failure occurred.
测试原则
As long as your tests are sensibly arranged, they won’t become unmanageable. Good rules-of-thumb include having:
- a separate
TestClass
for each model or view - a separate test method for each set of conditions you want to test
- test method names that describe their function