首先我们聊一下django的前世今生,据说03年的时候下面这几家公司开始使用python构建网站,
Lawrence Journal-World newspaper
Adrian Holovaty
Simon Willison
这几家公司的工作性质都有一个共同的特点就是每天需要不停的处理各类新闻事务、作品,话说当时编辑部门提出的需求变化之快让技术部门毫无招架之力,所以django就在这年诞生了,django与其快速开发的特性,方便的model管理,MTV模型(model-template-view)成就了djano在python web领域的霸主地位,下面的演示将带大家一起领略django的神奇魅力。
步骤
1、环境准备,安装django3.0版本,mysql驱动
2、创建一个项目,并设置settings
3、初始化数据库,创建django超级用户用于后台model管理
4、创建一个app,在settings注册app,在models.py创建模型,并在admin.py注册model,生成迁移文件并同步到数据库
5、app下views创建视图层
6、app下创建urls路由配置文件,并为视图层配置跳转
7、app下创建templates/appName/结构目录,并在目录下创建视图层对应的html模板
8、效果展示
9、使用django view模板,简化代码量
10、static静态资源使用
1、安装django3.0版本,指定安装源为国内豆瓣源
pip install django==3.0 -i http://pypi.douban.com/simple --trusted-host pypi.douban.com
pip install -i http://pypi.douban.com/simple --trusted-host pypi.douban.com mysqlclient
django-admin startproject djangotest
2、settings.py设置
# 设置显示语言
from django.utils.translation import gettext_lazy as _
LANGUAGES = [
('zh-Hans', _('Chinese')),
]
LANGUAGE_CODE = 'zh-Hans'
# 设置时区
TIME_ZONE = 'Asia/Shanghai'
# 设置数据库,默认使用sqlite3,这里使用mysql
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': 'django',
'USER': 'root',
'PASSWORD': 'root',
'HOST': '127.0.0.1',
'PORT': '3306',
}
}
3、初始化数据库
3-1 在数据库执行下面命令创建django库
create database django default charset utf8;
3-2 在项目下执行python manage.py migrate 同步django后台管理的相关表
3-3 创建超级用户用于django后台登陆,管理model
python manage.py createsuperuser
3-4 启动项目,访问http://127.0.0.1:8000,http://127.0.0.1:8000/admin
python manage.py runserver
4、创建一个app,在settings注册app,在models.py创建模型,并在admin.py注册model,生成迁移文件并同步到数据库
4-1 创建一个民意调查的app,需求,我们需要对网友关注的问题进行网络投票,一个问题对应多种答案,每个网民可以对其中的一个答案进行投票
python manage.py startapp polls
4-2 在settings.py INSTALLED_APPS增加polls app
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'polls.apps.PollsConfig',
]
4-3 models.py创建model模型
from django.db import models
# 继承Model,django会自动识别并在数据库创建该表
class Question(models.Model):
question_text = models.CharField(max_length=200)
pub_date = models.DateTimeField('date published')
# 用于django后台显示该字段
def __str__(self):
return self.question_text
class Choice(models.Model):
# 一对多关系,删除question时,对应的choice也会删除
question = models.ForeignKey(Question, on_delete=models.CASCADE)
choice_text = models.CharField(max_length=200)
votes = models.IntegerField(default=0)
def __str__(self):
return self.choice_text
4-4 admin.py注册 model
from django.contrib import admin
from .models import Question, Choice
admin.site.register(Question)
admin.site.register(Choice)
4-5 生成迁移文件,并同步到数据库
python manage.py makemigrations
python manage.py migrate
4-6 后台可以看到已更新刚注册的model
4-7 增加几个quesiton,并对question设置几个选项
5、polls/views.py创建视图层
from django.shortcuts import render, get_object_or_404
from django.http import HttpResponseRedirect
from .models import Question, Choice
from django.urls import reverse
# 获取最近相关的5个问题
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)
# 投票页面
def detail(request, question_id):
question = get_object_or_404(Question, pk=question_id)
return render(request, 'polls/detail.html', {'question': question})
# 投票处理
def vote(request, question_id):
question = get_object_or_404(Question, pk=question_id)
try:
# POST请求的key需要与detail.html input name属性保持一致
selected_choice = question.choice_set.get(pk=request.POST['choice'])
except(KeyError, Choice.DoesNotExist):
return render(request, 'polls/detail.html',{
'question':question,
'error_message': "You didn't select a choice"
})
else:
selected_choice.votes += 1
selected_choice.save()
return HttpResponseRedirect(reverse('polls:results', args=(question.id,)))
# 投票结果展示
def results(request, question_id):
question = get_object_or_404(Question, pk=question_id)
return render(request, 'polls/results.html', {'question':question})
6、app下创建urls.py路由配置文件,并为视图层配置跳转
from django.urls import path
from . import views
# app命名空间,django一个项目包含n个app,使用命名可以可以对url进行分类
app_name = 'polls'
urlpatterns = [
path('', views.index, name='index'),
path('<int:question_id>/', views.detail, name='detail'),
path('<int:question_id>/vote/', views.vote, name='vote'),
path('<int:question_id>/results/', views.results, name='results'),
]
项目路由配置
from django.contrib import admin
from django.urls import path, include
urlpatterns = [
path('admin/', admin.site.urls),
path('polls/', include('polls.urls')),
]
7、app下创建templates/appName/结构目录,并在目录下创建视图层对应的html模板,下面的是django模板的固定写法.
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
{% if latest_question_list %}
<ul>
{% for question in latest_question_list %}
<li> <a href="{% url 'polls:detail' question.id %}">{{ question.question_text }}</a> </li>
{% endfor %}
</ul>
{% else %}
<p> don't have resources </p>
{% endif %}
</body>
</html>
detail.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1> {{ question.question_text }} </h1>
{% if error_message %} <p> <strong> {{ error_message }} </strong> </p> {% endif %}
<form action="{% url 'polls:vote' question.id %}" method="post">
{% csrf_token %}
<ul>
{% 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>
{% endfor %}
</ul>
<input type="submit" value="Vote">
</form>
</body>
</html>
results.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1> {{ question.question_text }} </h1>
<ul>
{% for choice in question.choice_set.all %}
<li> {{ choice.choice_text }} -- {{ choice.votes }} </li>
{% endfor %}
</ul>
<a href="{% url 'polls:vote' question.id %}"> Vote again? </a>
</body>
</html>
8、效果展示
index首页
投票页面
结果展示页面
9、django为单个model或model list集合提供了模板,对于上面的index,detail,results,都是查询model或model集合,下面对这些view进行简化
9-1 修改views.py, urls.py如下
views.py
from django.http import HttpResponseRedirect
from django.urls import reverse
from django.shortcuts import get_object_or_404, render
from django.views import generic
from .models import Question, Choice
class IndexView(generic.ListView):
template_name = 'polls/index.html'
context_object_name = 'latest_question_list'
def get_queryset(self):
return Question.objects.order_by('-pub_date')[:5]
# django DetailView模板 默认返回的是<app name>/<model name>_detail.html,你甚至可以不指定template_name,
# 只要你按照相应的规则创建html
class DetailView(generic.DetailView):
model = Question
template_name = 'polls/detail.html'
class ResultsView(generic.DetailView):
model = Question
template_name = 'polls/results.html'
def vote(request, question_id):
question = get_object_or_404(Question, pk=question_id)
try:
# POST请求的key需要与detail.html input name属性保持一致
selected_choice = question.choice_set.get(pk=request.POST['choice'])
except(KeyError, Choice.DoesNotExist):
return render(request, 'polls/detail.html',{
'question':question,
'error_message': "You didn't select a choice"
})
else:
selected_choice.votes += 1
selected_choice.save()
return HttpResponseRedirect(reverse('polls:results', args=(question.id,)))
urls.py
from django.urls import path
from . import views
app_name = 'polls'
# 这里使用主键代替上面的question_id
urlpatterns = [
path('', views.IndexView.as_view(), name='index'),
path('<int:pk>/', views.DetailView.as_view(), name='detail'),
path('<int:pk>/results/', views.ResultsView.as_view(), name='results'),
path('<int:question_id>/vote/', views.vote, name='vote'),
]
10、django给我们每一个app提供了静态资源的管理,创建<app name>/static/<app name>/style.css
index.html引用样式
{% load static %}
<link rel="stylesheet" type="text/css" href="{% static 'polls/style.css' %}">