内容简介:摘要:日常学习中对一些知识点进行总结得出该系列文章。学习笔记内容包括前端技术,Django web开发技术,数据库技术如MySQL,MongoDB,PGSQL等等。此外还有一些工具如Dock,ES等等。(本文原创,转载必须注明出处.)(1)查看python版本号:(2) 创建Django项目
摘要:日常学习中对一些知识点进行总结得出该系列文章。学习笔记内容包括前端技术,Django web开发技术,数据库技术如MySQL,MongoDB,PGSQL等等。此外还有一些 工具 如Dock,ES等等。(本文原创,转载必须注明出处.)
(1)查看 python 版本号:
python -m django --version
(2) 创建Django项目
django-admin startproject mysite
(3)测试开发服务器是否成功
Desktop\bncDjango\mysite>python manage.py runserver
(4)创建应用模块
python manage.py startapp polls
# Application definition INSTALLED_APPS = [ 'django.contrib.admin', # 管理员站点 'django.contrib.auth', # 认证授权系统 'django.contrib.contenttypes', # 内容类型框架 'django.contrib.sessions', # 会话框架 'django.contrib.messages', # 消息框架 'django.contrib.staticfiles', #管理静态文件的框架 'polls', # 投票模块 ]
(5)polls模型下编辑视图view
from django.shortcuts import render # Create your views here. from django.http import HttpResponse def index(request): return HttpResponse("Hello,this is my frist polls index.")
(6)polls模块下映射url
from django.urls import path from . import views urlpatterns = [ path('', views.index,name='index'), ]
(7)mysite主模块下配置url
from django.contrib import admin from django.urls import path,include # 注意导入include模块 urlpatterns = [ path('polls/', include('polls.urls')), # 配置polls子模板url,支持正则 path('admin/', admin.site.urls), ]
(8)网页查询 http://localhost:8000/polls/
(9)数据库配置与迁移
DATABASES = { 'default': { # 'django.db.backends.sqlite3', # 'django.db.backends.postgresql', # 'django.db.backends.mysql', # 'django.db.backends.oracle' 'ENGINE': 'django.db.backends.sqlite3', 'NAME': os.path.join(BASE_DIR, 'db.sqlite3'), }, # MySQL数据库配置 # 'mysql': { # 'ENGINE': 'django.db.backends.mysql', # 'NAME': 'all_news', # 数据库名 # 'USER': 'root', # 'PASSWORD': 'root', # 'HOST': '127.0.0.1', # 'PORT': '3306', # } }
python manage.py migrate
(10)编写模型M
from django.db import models # Create your models here. class Question(models.Model): question_text = models.CharField(max_length=200) pub_data = models.DateField('date published') def __str__(self): return self.question_text class Choice(models.Model): 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
(11)激活模型
为模型的改变生成迁移文件python manage.py makemigrations polls
另一种查看,选择执行 接收一个迁移的名称,然后返回对应的 SQL
python manage.py sqlmigrate polls 0001
python manage.py migrate
(12)全自动后台管理页面
12.1 创建一个能登录管理页面的用户,均为admin
python manage.py createsuperuser
12.2 启动开发服务器:
python manage.py runserver
http://127.0.0.1:8000/admin/login/?next=/admin/
12.3 进入站点
12.4 管理页面中加入配置应用
from django.contrib import admin # Register your models here. from .models import Question,Choice admin.site.register(Question) admin.site.register(Choice)
(13)编写更多视图
13.1 polls下的views
from django.shortcuts import render from django.http import HttpResponse # 问题索引页 def index(request): return HttpResponse("Hello,this is my frist polls index.") # 问题详情页 def detail(request,question_id): return HttpResponse("You're looking at question %s." % question_id) # 问题结果页 def results(request,question_id): return HttpResponse("You're looking at the results of question %s." % question_id) # 投票处理器 def vote(request,question_id): return HttpResponse("You're voting on question %s." % question_id)
13.2 polls下的urls记得添加命名空间
from django.urls import path from . import views app_name = 'polls' #添加命名空间 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'), ]
13.3 查询数据库信息并页面显示
# 问题索引页 def index(request): latest_question_list = Question.objects.order_by('pub_data')[:3] output = '<br/>'.join([q.question_text for q in latest_question_list]) HttpResponse(template.render(context,request)) return HttpResponse(output)
(14)编写模板T
14.1 在mysite下创建templates,并创建polls文件夹下创建index.html
<!DOCTYPE html> <html> <head> <title>投票页面</title> </head> <body> {% 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 %} </body> </html>
.想改成 `polls/specifics/12/` ,你不用在模板里修改任何东西(包括其它模板),只要在 `polls/urls.py` 里稍微修改一下就行:
<ul> {% for question in latest_question_list %} <li><a href="{% url 'polls:detail' question.id %}">{{ question.question_text }}</a></li> {% endfor %} </ul>
14.2 在mysite的settings修改DIRS
TEMPLATES = [ { 'BACKEND': 'django.template.backends.django.DjangoTemplates', 'DIRS': [os.path.join(BASE_DIR,'template/')], 'APP_DIRS': True, 'OPTIONS': { 'context_processors': [ 'django.template.context_processors.debug', 'django.template.context_processors.request', 'django.contrib.auth.context_processors.auth', 'django.contrib.messages.context_processors.messages', ], }, }, ]
14.3 polls/views.py 修改
from django.shortcuts import render from django.http import HttpResponse from django.template import loader from polls.models import Question # 问题索引页 def index(request): latest_question_list = Question.objects.order_by('pub_data')[:5] # output = '<br/>'.join([q.question_text for q in latest_question_list]) template = loader.get_template('polls/index.html') context = { 'latest_question_list': latest_question_list, } return HttpResponse(template.render(context,request))
# 问题索引页 def index(request): latest_question_list = Question.objects.order_by('pub_data')[:5] context = {'latest_question_list': latest_question_list} return render(request,'polls/index.html',context)
14.4 在浏览器访问 “/polls/“ 查看:
(15)查看详细页面
15.1 polls下views.py
from django.http import Http404 # 问题详情页 def detail(request,question_id): try: question = Question.objects.get(pk=question_id) except Question.DoesNotExist: raise Http404("Question does not exist") return render(request,'polls/detail.html', {'question':question,'question_id':question_id})
from django.shortcuts import render,get_object_or_404 # 问题详情页 def detail(request,question_id): question = get_object_or_404(Question, pk=question_id) return render(request, 'polls/detail.html', {'question': question,'question_id':question_id})
15.2 template下detail.html
<!DOCTYPE html> <html> <head> <title>详细问题页面</title> </head> <body> <h1>{{ question.question_text }}</h1> <ul> {% for choice in question.choice_set.all %} <li>{{ choice.choice_text }}</li> {% endfor %} </ul> </body> </html>
15.3 运行结果
(16)polls/detail.html详细页面添加一个表单form
<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 %}` `{% 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 %}` <input type="submit" value="Vote"/> </form> </body>
- 每个单选按钮的
value
属性是对应的各个 Choice 的 ID。每个单选按钮的name
是"choice"
。这意味着,当有人选择一个单选按钮并提交表单提交时,它将发送一个 POST 数据choice=#
,其中# 为选择的 Choice 的 ID。这是 HTML 表单的基本概念。 - 我们设置表单的
action
为 { % url “polls:vote” question.id %} ,并设置method="post"
。使用 method=”post”是非常重要的,因为这个提交表单的行为会改变服务器端的数据。当你需要创建一个改变服务器端数据的表单时,请使用method="post"
。这不是 Django 的特定技巧;这是优秀的网站开发技巧。 - forloop.counter
指示 [
for`]( https://docs.djangoproject.com/zh-hans/2.2/ref/templates/builtins/#std:templatetag-for ) 标签已经循环多少次。 - 由于我们创建一个 POST 表单(它具有修改数据的作用),所以我们需要小心跨站点请求伪造。 谢天谢地,你不必太过担心,因为 Django 已经拥有一个用来防御它的非常容易使用的系统。 简而言之,所有针对内部 URL 的 POST 表单都应该使用{ % csrf_token %}模板标签。
(17) polls/views.py
视图编辑
# 投票处理器 def vote(request,question_id): question = get_object_or_404(Question, pk=question_id) try: 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,)))
-
request.POST
是一个类字典对象,让你可以通过关键字的名字获取提交的数据。 这个例子中,request.POST['choice']
以字符串形式返回选择的 Choice 的 ID。request.POST
的值永远是字符串。 - 如果在
request.POST['choice']
数据中没有提供choice
, POST 将引发一个KeyError
。上面的代码检查KeyError
,如果没有给出choice
将重新显示 Question 表单和一个错误信息。 - 在增加 Choice 的得票数之后,代码返回一个
HttpResponseRedirect
而不是常用的HttpResponse
、HttpResponseRedirect
只接收一个参数:用户将要被重定向的 URL。构造函数中使用reverse()
函数。这个函数避免了我们在视图函数中硬编码 URL。重定向的 URL 将调用'results'
视图来显示最终的页面。
(18) 重定向results.html
from django.shortcuts import get_object_or_404, render def results(request, question_id): question = get_object_or_404(Question, pk=question_id) return render(request, 'polls/results.html', {'question': question})
(19)通用视图,代码重构
19.1 detail()
视图几乎一模一样。唯一的不同是模板的名字。
# 问题索引页 def index(request): latest_question_list = Question.objects.order_by('pub_data')[:5] return render(request,'polls/index.html',{'latest_question_list': latest_question_list}) # 问题详情页 def detail(request,question_id): question = get_object_or_404(Question, pk=question_id) return render(request, 'polls/detail.html', {'question': question,'question_id':question_id}) # 问题结果页 def results(request,question_id): question = get_object_or_404(Question, pk=question_id) return render(request, 'polls/results.html', {'question': question})
19.2 创建一个 polls/results.html
模板
<h1>{{ question.question_text }}</h1> <ul> `{% for choice in question.choice_set.all %}` <li>`{{ choice.choice_text }} -- {{ choice.votes }} vote{{ choice.votes|pluralize }}`</li> {% endfor %} </ul> <a href="{% url 'polls:detail' question.id %}">Vote again?</a>
19.3 通用视图系统
通用视图将常见的模式抽象化,可以使你在编写应用时甚至不需要编写Python代码。将我们的投票应用转换成使用通用视图系统,这样我们可以删除许多我们的代码。我们仅仅需要做以下几步来完成转换,
- 转换 URLconf。
- 删除一些旧的、不再需要的视图。
- 基于 Django 的通用视图引入新的视图
1 改良URLconf
打开 polls/urls.py
这个 URLconf 并将它修改成:路径字符串中匹配模式的名称已经由 <question_id>
改为 <pk>
。
from django.urls import path from . import views app_name = 'polls' 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'), ]
2 改良视图
删除旧的 index
, detail
, 和 results
视图,并用 Django 的通用视图代替。打开 polls/views.py
文件,并将它修改成:
from django.http import HttpResponseRedirect from django.shortcuts import get_object_or_404, render from django.urls import reverse from django.views import generic from .models import Choice, Question 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] 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: 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,)))
- 每个通用视图需要知道它将作用于哪个模型。 这由
model
属性提供。 -
DetailView
期望从 URL 中捕获名为"pk"
的主键值,所以我们为通用视图把question_id
改成pk
。
19.4 运行程序
主页面
子页面
详情页面
(20)自动化测试
20.1 测试的策略
- 测试驱动:写代码之前先写测试。「测试驱动」的开发方法只是将问题的描述抽象为了 Python 的测试样例。
- 更普遍的情况是,一个刚接触自动化测试的新手更倾向于先写代码,然后再写测试。
- 如果你才写了几千行 Python 代码,选择从哪里开始写测试确实不怎么简单。如果是这种情况,那么在你下次修改代码(比如加新功能,或者修复 Bug)之前写个测试是比较合理且有效的。
20.2 第一个测试
需求:我们的要求是如果 Question 是在一天之内发布,was_published_recently() 方法将会返回
True ,然而现在这个方法在
Question 的
pub_date` 字段比当前时间还晚时也会返回 True
编写测试代码:
from django.test import TestCase # Create your tests here. from django.utils import timezone from .models import Question class QuestionModelTests(TestCase): def test_was_published_recently_with_future_question(self): """ was_published_recently() returns False for questions whose pub_date is in the future. """ time = timezone.now() + datetime.timedelta(days=30) future_question = Question(pub_date=time) self.assertIs(future_question.was_published_recently(), False)
运行代码:$ python manage.py test polls
测试结果:
-
python manage.py test polls
将会寻找polls
应用里的测试代码 - 它找到了
django.test.TestCase
的一个子类 - 它创建一个特殊的数据库供测试使用
- 它在类中寻找测试方法——以
test
开头的方法。 - 在
test_was_published_recently_with_future_question
方法中,它创建了一个pub_date
值为 30 天后的Question
实例。 - 接着使用
assertls()
方法,发现was_published_recently()
返回了True
,而我们期望它返回False
。
(21)静态文件(图片/脚本/样式)
对于小项目来说,静态文件随便放在哪,只要服务程序能够找到它们就行。然而在大项目中,处理不同应用所需要的静态文件的工作就显得有点麻烦了。这就是 django.contrib.staticfiles
存在的意义
创建的 static
文件夹中创建 polls
的文件夹,再在 polls
文件夹中创建一个名为 style.css
的文件。样式表路径应是 polls/static/polls/style.css
。因为 AppDirectoriesFinder
的存在,你可以在 Django 中简单地使用以 polls/style.css
的形式引用此文件,类似你引用模板路径的方式。
li a { color: green; }
polls的index.html引用
<head> <title>投票页面</title> `{% load static %}` <link rel="stylesheet" type="text/css" href="{% static 'polls/style.css' %}"> </head>
添加图片
我们会创建一个用于存在图像的目录。在 polls/static/polls
目录下创建一个名为 images
的子目录。在这个目录中,放一张名为 background.gif
的图片。换言之,在目录 polls/static/polls/images/background.jpg
中放一张图片。
body { background: white url("images/background.gif") no-repeat; }
更多关于设置和框架的资料,参考 静态文件解惑 和 静态文件指南 。 部署静态文件 介绍了如何在真实服务器上使用静态文件。
(22) 编写第一个django应用
22.1 polls/admin定义后台表单,列表为字段显示顺序
from django.contrib import admin # Register your models here. from .models import Question,Choice class QuestionAdmin(admin.ModelAdmin): # fieldsets = [ # ('问题内容', {'fields': ['question_text']}), # ('发布时间', {'fields': ['pub_data']}), # ] # fields = ['pub_data', 'question_text'] list_display = ('question_text', 'pub_data') admin.site.register(Question, QuestionAdmin) class ChoiceAdmin(admin.ModelAdmin): # fields = ['question','choice_text', 'votes'] list_display = ('question','choice_text', 'votes') admin.site.register(Choice, ChoiceAdmin)
22.2 字段过滤器
class QuestionAdmin(admin.ModelAdmin): list_display = ('question_text', 'pub_data') list_filter = ['pub_data'] # 过滤器 admin.site.register(Question, QuestionAdmin)
22.3 自定义后台界面与风格
- 打开你的设置文件(
mysite/settings.py
,牢记),在TEMPLATES
设置中添加DIRS
选项: - 在
templates
目录内创建名为admin
的目录,随后,将存放 Django 默认模板的目录(django/contrib/admin/templates
)内的模板文件admin/base_site.html
复制到这个目录内。 Django 的源文件在哪里? $ python -c “import django; print(django. path )” - 完成后,你应该看到如下代码:
`{% block branding %}` <h1 id="site-name"><a href="{% url 'admin:index' %}">Polls Administration</a></h1> `{% endblock %}`
技术交流共享QQ群
【 机器学习和自然语言QQ群:436303759 】 :
机器学习和自然语言(QQ群号:436303759)是一个研究深度学习、机器学习、自然语言处理、数据挖掘、图像处理、目标检测、数据科学等AI相关领域的技术群。其宗旨是纯粹的AI技术圈子、绿色的交流环境。本群禁止有违背法律法规和道德的言谈举止。群成员备注格式:城市-自命名。微信订阅号:datathinks
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。