创建项目
安装依赖包:
pip install Django
python -m django --version
创建项目:
django-admin startproject mysite
得到:
mysite/ --项目目录,名字可以随意起
manage.py --用于与项目交互的命令行脚本
mysite/ --项目的Python包,后面需要引入的话需要写成类似 import mysite.urls
__init__.py --标记该目录为一个Python包
settings.py --项目配置文件
urls.py --项目url说明
asgi.py --兼容asgi web服务器的入口
wsgi.py --兼容wsgi web服务器的入口
运行网站:
cd mysite
python manage.py runserver
访问http://127.0.0.1:8000/能看到:
自定义端口:
python manage.py runserver 8080
自定义IP(0是0.0.0.0的简写):
python manage.py runserver 0:8000
现在用的是Django自带的测试环境服务器,不建议用于生产环境。
创建app
项目= app + 配置。一个项目能包含多个app,一个app可属于多个项目。
在当前项目下创建一个新的app:
python manage.py startapp polls
得到如下目录结构:
polls/
__init__.py
admin.py
apps.py
migrations/
__init__.py
models.py
tests.py
views.py
编辑views.py,添加:
from django.http import HttpResponse
def index(request):
return HttpResponse("Hello Django!")
新建urls.py,添加:
from django.urls import path
from . import views
urlpatterns = [
path('', views.index, name='index')
]
编辑mysite\mysite\urls.py,添加:
from django.contrib import admin
from django.urls import path, include
urlpatterns = [
path('admin/', admin.site.urls),
path('polls/', include('polls.urls')), #引用其它URLconf文件
]
include能引用其它URLconf文件,当Django遇到这个include时,会将url中匹配该入口点的部分’polls/'截掉,剩下的部分发给polls.url进一步处理。
现在重新启动服务器,访问http://127.0.0.1:8000/polls/,即可看到:
Hello Django!
urls.py中的path函数很关键:
path('', views.index, name='index')
# views.index
def index(request):
return HttpResponse("Hello Django!")
path()函数有4个参数:
- route,url 模式
- view,当找到匹配的route时,调用对应的view函数,返回的是一个HttpRequest对象
- kwargs (可选)
- name (可选)
修改settings.py
配置数据库
mysite\settings.py中有数据库配置选项:
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': BASE_DIR / 'db.sqlite3',
}
}
默认用python自带的sqlite3。
ENGINE可以替换为:
‘django.db.backends.sqlite3’,
‘django.db.backends.postgresql’,
‘django.db.backends.mysql’,
‘django.db.backends.oracle’
NAME为数据库名,默认在项目根目录(BASE_DIR)存储sqlite数据库文件:
配置语言和时区
setting.py配置语言和时区为中国:
# Chinese Shanghai
LANGUAGE_CODE = 'zh-hans'
TIME_ZONE = 'Asia/Shanghai'
# db does not use utc time
USE_TZ = False
配置INSTALLED_APPS
Django的app是“可插拔的”,INSTALLED_APPS指定了项目中所有活动的app名称(app可被用于多个项目),默认有:
INSTALLED_APPS = [
'django.contrib.admin', # 管理页面
'django.contrib.auth', # 认证系统
'django.contrib.contenttypes', # 内容类型框架
'django.contrib.sessions', # session框架
'django.contrib.messages', # 消息框架
'django.contrib.staticfiles', # 静态文件管理框架
]
这些app可能会用到数据库中的一个或多个表,所以在使用这些app前要创建数据库:
python manage.py migrate
migrate指令会检查所有活动app,并创建它们所需的数据库表。上述指令创建出的表如下:
如果不需要某些app,可以在执行migrate命令前注释掉。
创建Model
在polls/models.py中添加:
from django.db import models
class Question(models.Model):
question_text = models.CharField(max_length=200)
pub_date = models.DateTimeField('date published') # human-readable name
class Choice(models.Model):
questions = models.ForeignKey(Question, on_delete=models.CASCADE)
choice_text = models.CharField(max_length=200)
votes = models.IntegerField(default=0)
接着要在settings.py中添加poll app。
polls/app.py默认为:
from django.apps import AppConfig
class PollsConfig(AppConfig):
default_auto_field = 'django.db.models.BigAutoField'
name = 'polls'
只需把PollsConfig包含到INSTALLED_APPS即可:
INSTALLED_APPS = [
'polls.apps.PollsConfig', # 添加polls
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
]
现在可以执行:
python manage.py makemigrations polls
显示:
Migrations for 'polls':
polls/migrations/0001_initial.py
- Create model Question
- Create model Choice
makemigrations命令告诉Django models有变化,需要将变化存储为migration(migration是Django用来存储models变化的文件)。
然后运行命令:
python manage.py sqlmigrate polls 0001
能看到针对项目数据库类型自动生成的sql语句:
BEGIN;
--
-- Create model Question
--
CREATE TABLE "polls_question" ("id" integer NOT NULL PRIMARY KEY AUTOINCREMENT, "question_text" varchar(200) NOT NULL, "pub_date" datetime NOT NULL);
--
-- Create model Choice
--
CREATE TABLE "polls_choice" ("id" integer NOT NULL PRIMARY KEY AUTOINCREMENT, "choice_text" varchar(200) NOT NULL, "votes" integer NOT NULL, "questions_id" bigint NOT NULL REFERENCES "polls_question" ("id") DEFERRABLE INITIALLY DEFERRED);
CREATE INDEX "polls_choice_questions_id_d356887e" ON "polls_choice" ("questions_id");
COMMIT;
注意:
- 表名默认为 app名_模型名
- 主键会自动生成(可以覆写)
- 外键名为’关联表名_id’ (也可以覆写)
- 外键关系会被 FOREIGN KEY 约束显式指出
sqlmigrate指令只是打印出建表语句,并没真正执行这些sql。
也可以执行python manage.py check
来在真正改动数据库前检查项目中的问题。
现在可以再次执行migrate指令了:
python manage.py migrate
它会为上述models在database中建表。现在数据库中的表如下:
django_migrations表中记录了所有未应用的migration,migrate指令会执行这些migration。
至此,总结一下修改model的步骤:
- 修改models.py中的model;
- 执行
python manage.py makemigrations
来创建这些改动的migration - 执行
python manage.py migrate
使这些migration应用到数据库
专门记录migration,可以便于在版本控制系统中管理,也能让其它开发者使用。
玩转API
在python shell中可以使用Django提供的各种api。
打开python shell:
python manage.py shell
之所以不直接敲python
,是因为manage.py设置了DJANGO_SETTINGS_MODULE环境变量,能让python导入settings.py。
在shell中可以尝试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