创建项目
创建虚拟环境
1 2 3 conda create -n testDjango python=3.8 conda activate testDjango pip install Django # 注意这里Django首字母大写
创建项目
1 2 cd D:\PythonCode django-admin startproject mysite
创建成功的项目结构为:
1 2 3 4 5 6 7 8 mysite/ manage.py mysite/ __init__.py settings.py urls.py asgi.py wsgi.py
启动服务器:
1 2 cd mysite python manage.py runserver
创建应用
项目=(一个及以上的)应用程序 + 配置
创建应用
1 2 # 项目名称为"polls" python manage.py startapp polls
创建成功的应用结构为:
1 2 3 4 5 6 7 8 9 polls/ __init__.py admin.py apps.py migrations/ __init__.py models.py tests.py views.py
创建首页
1 2 3 4 5 6 # 修改polls/views.py,创建index view from django.http import HttpResponse def index(request): return HttpResponse("Hello, world. You're at the polls index.")
配置url
应用的url配置文件
1 2 3 4 5 6 7 8 9 10 11 12 13 # 新增polls/urls.py, 用于配置应用"polls"下的url from django.urls import path from . import views # 设置应用程序命名空间 # 在真正的 Django 项目中,可能有五个、十个、二十个或更多应用程序。Django 如何区分它们之间的 URL 名称?——即将命名空间app_name = "polls"添加到 URLconf 中 app_name = "polls" urlpatterns = [ path("", views.index, name="index"), ]
项目的url配置文件
1 2 3 4 5 6 7 8 9 # 修改mysite/urls.py,将应用"polls"下的urls.py引入 from django.contrib import admin from django.urls import include, path urlpatterns = [ path("polls/", include("polls.urls")), path("admin/", admin.site.urls), ]
启动服务器:
1 python manage.py runserver
启动服务器后访问链接:http://127.0.0.1:8000/polls/,即可访问到index
view
连接Database
1 2 3 4 5 6 7 8 9 10 11 12 13 # 在项目的settings.py(即mysite/settings.py)中修改数据库配置 # 修改数据库配置——更改为mysql数据库 DATABASES = { 'default': { 'ENGINE': 'django.db.backends.mysql', 'NAME': 'db_test', "USER": "root", "PASSWORD": "123456xjy", "HOST": "127.0.0.1", "PORT": "3306", } }
1 2 3 # 首次连接mysql数据库需要在虚拟环境导入以下2个包 pip install pymysql pip install mysqlclient
1 2 # 执行数据迁移——将"mysite/settings.py"中INSTALLED_APPS对应的数据表都创建出来(创建到上述的"db_test"数据库中) python manage.py migrate
建立Model
步骤
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.
Change your models
1 2 3 4 5 6 7 8 9 10 11 12 13 # 修改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") class Choice(models.Model): question = models.ForeignKey(Question, on_delete=models.CASCADE) choice_text = models.CharField(max_length=200) votes = models.IntegerField(default=0)
make migrations
将应用"polls"放到项目的setting.py(即mysite/settings.py)的INSTALLED_APPS中
1 2 3 4 5 6 7 8 9 10 11 # 修改mysite/settings.py,增加一行"polls.apps.PollsConfig", INSTALLED_APPS = [ "polls.apps.PollsConfig", "django.contrib.admin", "django.contrib.auth", "django.contrib.contenttypes", "django.contrib.sessions", "django.contrib.messages", "django.contrib.staticfiles", ]
make migrations
1 python manage.py makemigrations polls
migrate
1 2 # 运行以下代码,即可将models.py中新创建的类Question和类Choice,在数据库中创建出对应的数据表 python manage.py migrate
进入Python环境
We’re using this instead of simply typing “python”, because
manage.py
sets the DJANGO_SETTINGS_MODULE
environment variable, which gives Django the Python import path to your
mysite/settings.py
file.
管理后台
创建超级管理员
1 python manage.py createsuperuser
运行服务器
1 python manage.py runserver
将自定义的类注册到管理后台
1 2 3 4 5 6 # 修改polls/admin.py,将新注册的类Question注册到管理后台 from django.contrib import admin from .models import Question admin.site.register(Question)
增加Views
新增视图
每一个View就干两件事中的一件:要么返回一个HttpResponse,要么返回一个Exception(如Http404)
1 2 3 4 5 6 7 8 9 10 11 12 # 在polls/views.py新增以下函数(视图) # 以下均为虚拟实现 def detail(request, question_id): return HttpResponse("You're looking at question %s." % question_id) def results(request, question_id): response = "You're looking at the results of question %s." return HttpResponse(response % question_id) def vote(request, question_id): return HttpResponse("You're voting on question %s." % question_id)
配置应用url
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 # 将新增的view写入pools/urls.py from django.urls import path from . import views urlpatterns = [ # ex: /polls/ path("", views.index, name="index"), # ex: /polls/5/ path("<int:question_id>/", views.detail, name="detail"), # ex: /polls/5/results/ path("<int:question_id>/results/", views.results, name="results"), # ex: /polls/5/vote/ path("<int:question_id>/vote/", views.vote, name="vote"), ]
用户访问视图的运行流程
请求页面"/polls/6/"=>加载mysite.urls=>找到变量"polls/"命名的urlpatterns,即path("polls/", include("polls.urls"))
=>去掉"polls/",剩余"6/"=>把剩余的"6/"发送给"polls.urls
"
URLconf=>匹配到了path("<int:question_id>/", views.detail, name="detail")
=>导致调用了detail()
视图(views.py中的detail()
),具体调用如detail(request=<HttpRequest object>, question_id=34)
修改Views
index view
上述增加视图中的视图使用了虚拟实现,并没有从数据库中读取记录,或完成其他有实际意义的任务,因此在这一板块将编写实际执行某些操作的视图。
修改视图(index view)
法1:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 # polls/views.py # 修改index view (index函数),使用模板(利用HttpResponse和loader),读取数据库数据 # 加载调用的模板 polls/index.html并向其传递context。context是将模板变量名称映射到 Python 对象的字典。 from django.http import HttpResponse from django.template import loader from .models import Question def index(request): latest_question_list = Question.objects.order_by("-pub_date")[:5] template = loader.get_template("polls/index.html") context = { "latest_question_list": latest_question_list, } return HttpResponse(template.render(context, request))
法2:
利用render()函数代替HttpResponse和loader,简化代码
render()
函数第一个参数是请求对象,第二个参数是模板名称,第三个参数是可选的字典。它返回一个HttpResponse
对象,这是一个使用给定context的模板对象。
1 2 3 4 5 6 7 8 9 10 11 # polls/views.py from django.shortcuts import render from .models import Question def index(request): latest_question_list = Question.objects.order_by("-pub_date")[:5] context = {"latest_question_list": latest_question_list} return render(request, "polls/index.html", context)
创建模板(index.html)
如果页面的设计硬编码在视图中,那么当我们想要更改页面的外观时,必须编辑此
Python
代码(即views.py中的函数)。因此我们使用Django的模板系统,通过创建模板,使得页面设计与Python代码分离。
在应用的目录下创建templates目录(即polls/templates/),Django会默认在这个目录下寻找模板。
创建好模板文件后的目录结构如下:
1 2 3 4 5 6 7 8 9 10 11 # 这里还在templates目录下创建了一个polls子目录,在子目录下才放置了模板文件index.html # 这里新建的polls子目录起到划分命名空间的作用。因为如果在不同的应用程序中具有相同名称的模板,Django 将无法区分它们,所以需要设置命名空间。 polls/ __init__.py admin.py models.py views.py templates polls index.html
index.html的文件内容如下:
1 2 3 4 5 6 7 8 9 10 11 # polls/templates/polls/index.html {% if latest_question_list %} <ul> {% for question in latest_question_list %} <li><a href="/polls/{{ question.id }}/">{{ question.question_text }}</a></li> {% endfor %} </ul> {% else %} <p>No polls are available.</p> {% endif %}
移除模板文件中的硬编码URL
1 2 3 4 5 6 7 8 9 10 11 # 修改前 <li><a href="/polls/{{ question.id }}/">{{ question.question_text }}</a></li> # 修改后 <li><a href="{% url 'detail' question.id %}">{{ question.question_text }}</a></li> # 修改原因:在polls/urls.py中,views.py的detail()函数路径被注册为 path("<int:question_id>/", views.detail, name="detail"),其中name属性为"detail" # 继续修改:在polls/urls.py中设置应用程序命名空间(app_name = "polls")后,继续修改为指向命名空间的详细视图 <li><a href="{% url 'polls:detail' question.id %}">{{ question.question_text }}</a></li>
detail view
修改视图(detail view)
使用get方法特别容易产生404错误,因此产生了一个快捷方式,即使用get_object_or_404()
来进行查询。get_object_or_404()
第一个参数是a
Django
model,第二个参数是任意数量的关键词参数。如果查询对象存在,则返回该模型对象;如果对象不存在,则返回Http404。
1 2 3 4 5 6 7 8 9 10 # polls/views.py from django.shortcuts import get_object_or_404, render from .models import Question def detail(request, question_id): question = get_object_or_404(Question, pk=question_id) return render(request, "polls/detail.html", {"question": question})
创建模板(detail.html)
1 2 3 4 5 6 7 8 9 10 11 12 <form action="{% url 'polls:vote' question.id %}" method="post"> {% csrf_token %} <fieldset> <legend><h1>{{ question.question_text }}</h1></legend> {% if error_message %}<p><strong>{{ error_message }}</strong></p>{% endif %} {% for choice in question.choice_set.all %} <input type="radio" name="choice" id="choice{{ forloop.counter }}" value="{{ choice.id }}"> <label for="choice{{ forloop.counter }}">{{ choice.choice_text }}</label><br> {% endfor %} </fieldset> <input type="submit" value="Vote"> </form>
2中的vote()函数还需要具体实现
后续内容可以参考官方文档https://docs.djangoproject.com/en/5.0/intro/tutorial04/