djangoproject/first_django_app.md

200 lines
7.2 KiB
Markdown
Raw Normal View History

2020-10-18 19:42:32 +11:00
# First Django App
Target: create a basic poll application, with 2 parts a **public site** and a **admin site**
* **public site**: let's pp view polls and vote
* **admin site**: let's you(admin) add/change/delete poll
2020-10-20 14:22:46 +11:00
## Part 1
1. Create web project
2. Create 1st app
3. Create 1st view
4. Add view & app into web url
### Creating a project
2020-10-18 20:07:45 +11:00
In the source directory, create project by
```
$ django-admin startproject <project_name>
```
Constraint on `<project_name>`:
* don't use names that conflict with django
* e.g. `django`, `test` (test with built-in test file)
```
mysite/
manage.py
mysite/
__init__.py
settings.py
urls.py
asgi.py
wsgi.py
```
Explain file structure:
* top-level `mysite/`: container of the project, can be renamed latter w/o affect Django framework
* `manage.py`: cmd-line utility let us to interact (admin) with Django projects.
* inner `mysite/` dir: actual Python package for the project.
* Importing any package from here: e.g. `mysite.urls`
* `mysite/__init__.py`: empty file, tell python start from here.
* `mysite/settings.py`: settings/config for this django project.
* `mysite/urls.py`: URL declarations for this Django pjt; a "table of contents" of this Django website.
* `mysite/asgi.py`: An entry-point for ASGI-compatible webservers
* `mysite/wsgi.py`: Entry-point for WSGI-compatible webservers
2020-10-20 14:22:46 +11:00
### The development server
2020-10-18 20:07:45 +11:00
Start server steps:
1. cd into outer `mysite/` dir
2. Start server via: `python manage.py runserver`
Outcome:
* A development server is started. So no need to config a production server (e.g. Apache)
* Note: don't use it as production environment.
2020-10-20 14:22:46 +11:00
### Creating the Polls app
2020-10-18 20:07:45 +11:00
> Projects vs. apps
>
> Whats 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 small 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.
Create a poll app along `mysite/`. For what?
```
$ python manage.py startapp polls
```
app hierarchy
```
polls/
__init__.py
admin.py
apps.py
migrations/
__init__.py
models.py
tests.py
views.py
```
2020-10-20 14:22:46 +11:00
### Write the first view
2020-10-18 20:45:21 +11:00
2020-10-20 14:22:46 +11:00
#### Step 1: Create a simple view of `polls` app
2020-10-18 20:45:21 +11:00
modify `polls/views.py` as
```python
from django.http import request
from django.shortcuts import render
def index(request):
return HttpResponse("Hello, world. You're at the polls index")
```
* `def index(request):...` is the simplest view
2020-10-20 14:22:46 +11:00
#### Step 2: In `polls` app, map the URL to this view
2020-10-18 20:45:21 +11:00
After creating a view, map it to a URL so we can call it. Create `polls/urls.py`, and setup mapping `urlpatterns`
```python
from django.urls import path
from . import views
urlpatterns = [
path('', views.index, name='index'),
]
```
2020-10-20 14:22:46 +11:00
#### Step 3: Point the root URLconf for polls
2020-10-18 20:45:21 +11:00
To point the root URLconf at `polls.urls` module:
1. In `mysite/urls.py`
1. add import for `django.urls.inclue`
2. insert a `include()` in `urlpatterns` list
i.e.
```python
from django.contrib import admin
from django.urls import include, path
urlpatterns = [
path('polls/', include('polls.urls')),
path('admin/', admin.site.urls),
]
```
2020-10-20 14:22:46 +11:00
##### django.urls.include()
2020-10-18 20:45:21 +11:00
> django.urls.include(): A function that takes a full Python import path to another URLconf module that should be “included” in this place.
* new imported `include()` function allows referencing other URLconfs.
* `'polls.urls'` is the package that we are using, hence `mysite` can connect to `polls` app
2020-10-20 14:22:46 +11:00
##### path()
2020-10-18 20:45:21 +11:00
Here `path()` function is passed **route** and **view**; two additional option available **kwargs**, and **name**
* `path()` argument **route**: a string that contains a URL pattern. When Django processing a request, it starts at the first pattern in `urlpatterns` and go down the list, comparing requested URL against each pattern
* `path()` argument **view**: when Django finds a matching pattern, it calls specified view function (a `HttpRequest` obj as the 1st argument, and others captured values as keyword argument)
* `path()` argument **kwargs**: passed in a dictionary to the target view
2020-10-20 10:39:20 +11:00
* `path()` argument **name**: naming URL, so we can refer to it elsewhere.
2020-10-20 14:22:46 +11:00
## Part 2
### Database setup
1. Modify `mysite/settings.py` for database binding
2. `python manage.py migrate` create database for each app
### Models Creation
在 Django 里写一个数据库驱动的 Web 应用的第一步: **定义模型** - 也就是数据库结构设计和附加的其它元数据 Meta Data
### Activate Models
改变模型需要这三步:
* 编辑 models.py 文件,改变模型
* 运行 python manage.py makemigrations 为模型的改变生成迁移文件。
* 运行 python manage.py migrate 来应用数据库迁移。
在这之前确认polls已经在 INSTALLED_APPS的settings中。
详情如何使用 `manage.py` 可check [Django后台文档](https://docs.djangoproject.com/zh-hans/3.1/ref/django-admin/)
### Test API
2020-10-20 10:39:20 +11:00
2020-10-20 15:25:39 +11:00
进入 `python manage.py shell` 可以使用Django创建的各种API如[数据库抽象API database API(建议细看)](https://docs.djangoproject.com/zh-hans/3.1/topics/db/queries/)
## Part 3
* In Django, web content & HTML come from Views models. Every view is a Python function/class. Django use customer requested URL to decide which View to generate.
* Django use 'URLconfs' to map btw URL and Views. Details of[pURL manager](https://docs.djangoproject.com/zh-hans/3.1/topics/http/urls/)
* URL's general form: `/newsarchive/<year>/<month>/`
### Create more Views
> 当某人请求你网站的某一页面时——比如说, "/polls/34/" Django 将会载入 mysite.urls 模块,因为这在配置项 ROOT_URLCONF 中设置了。然后 Django 寻找名为 urlpatterns 变量并且按序匹配正则表达式。在找到匹配项 'polls/',它切掉了匹配的文本("polls/"),将剩余文本——"34/",发送至 'polls.urls' URLconf 做进一步处理。在这里剩余文本匹配了 "<int:question_id>/",使得我们 Django 以如下形式调用 polls.urls.detail():
> `detail(request=<HttpRequest object>, question_id=34)`
2020-10-20 15:28:25 +11:00
### Create a true useful View
每个视图必须要做的只有两件事:返回一个包含被请求页面内容的 HttpResponse 对象,或者抛出一个异常,比如 Http404 。至于你还想干些什么,随便你。
你的视图可以从数据库里读取记录,可以使用一个模板引擎(比如 Django 自带的,或者其他第三方的),可以生成一个 PDF 文件,可以输出一个 XML创建一个 ZIP 文件,你可以做任何你想做的事,使用任何你想用的 Python 库。
2020-10-20 15:36:03 +11:00
`django.shortcuts.render` 可以“载入模板,填充上下文,再返回由它生成的 HttpResponse 对象“
### shortcut function: `render()`
「载入模板,填充上下文,再返回由它生成的 HttpResponse 对象」是一个非常常用的操作流程。于是 Django 提供了一个快捷函数 render
> The render() function takes the request object as its first argument, a template name as its second argument and a dictionary as its optional third argument. It returns an HttpResponse object of the given template rendered with the given context.