个人学习笔记,参考django官方文档:https://docs.djangoproject.com/zh-hans/3.2/
本文同步发表在我的个人博客上:https://sunguoqi.com/2021/12/09/Django_01/

文章目录

  • 一、First Django APP
  • 二、挂载 app
  • 三、编写model层
    • 1、使用Django可视化管理数据
    • 2、启动项目
  • 四、编写view层
  • 五、编写路由器
    • 1、挂载路由
    • 2、启动项目
  • 六、编写模板
  • 七、写点有用的视图
  • 八、路由分发的进阶
  • 九、去除模板中的硬编码 URL
  • 十、显示详情
  • 十一、编写表单
  • 十二、通用视图
    • 1、改良 URLconf
    • 2、改良视图

一、First Django APP

  上篇笔记从零创建了一个django项目,一个项目肯定是由多个模块组成的,比方说一个电商项目,包括支付模块,商品展示模块,商家用户聊天模块等等,这些模块便可称之为一个应用。
  本篇笔记继续跟着django官方文档创建了一个投票的应用。
  它由两部分组成:

  • 一个让人们查看和投票的公共站点。
  • 一个让你能添加、修改和删除投票的管理站点。

  在项目目录下,执行下面这行命令,创建一个应用。

python manage.py startapp polls

  此时app目录如下,各文件的作用在使用中揭晓。

polls/__init__.pyadmin.pyapps.pymigrations/__init__.pymodels.pytests.pyviews.py

二、挂载 app

  app创建完成,需要把app加载到整个项目上。
  为了避免项目名称和其他的一些模块名冲突,可以将'polls',写成,polls.apps.PollsConfig,注意格式,字符串列表需要用,分开。

settings.py

INSTALLED_APPS = ['polls','django.contrib.admin','django.contrib.auth','django.contrib.contenttypes','django.contrib.sessions','django.contrib.messages','django.contrib.staticfiles',
]

三、编写model层

  model层,是Django的数据管理层,负责和数据库交互,编写model层就是设计应用所需要的数据表,得益于Django的ORM模块,我们不必写SQL语句就可以操作数据表。
  model层里的一个类就是一个数据表,一行就是一个对象,一列就是一个对象的一个属性。

polls/models.py

# django框架的接口模块,默认已经引入
from django.db import models# Create your models here.# 创建了一个“问题”类(表),表里有两个字段。
class Question(models.Model):# 问题描述字段question_text = models.CharField(max_length=200)# 创建日期字段pub_date = models.DateTimeField('date published')# python魔法方法,显示调用该对象的时候的返回内容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)# python魔法方法,显示调用该对象的时候的返回内容def __str__(self):return self.choice_text

  model层写好了,数据表创建好了吗,并没有,我们还需要执行以下命令。

生成中间文件

python manage.py makemigrations polls

日志如下

  polls\migrations\0001_initial.py- Create model Question- Create model Choice

  django为我们生成了一个0001_initial.py,他是一个中间文件,执行迁移数据库的命令后,django会依赖这个文件去帮我们创建数据库表。

迁移数据

python manage.py migrate

日志如下

  Apply all migrations: admin, auth, contenttypes, polls, sessions
Running migrations:Applying polls.0001_initial... OK

  查看生成的表,撒花。

1、使用Django可视化管理数据

  表已经创建好了,如何使用django自带的后台可视化管理数据呢,这需要我们注册一下。(选项类也要注册到里面去,后面会用到)

polls/admin.py

# django的接口,默认已经引入。
from django.contrib import admin# 引入我们自己写的数据表(类)
from .models import Question# 注册以下就可以交给django后台管理啦!
# Register your models here.
admin.site.register(Question)

2、启动项目

  重新启动下项目,看下Django后台可不可以编辑我们的数据表。

python manage.py runserver

进入:http://127.0.0.1:8000/admin/

四、编写view层

  数据我们已经创建好了,也可以进行基本的CRUD操作了,接下来就是前端显示了对吧。view就是干这个的。
  view层可以和数据库交互,处理前端显示,但有些东西是不需要和数据库交互就可以显示的。
  所以我们先写一个Hello World展示在前端,然后再和model层结合,写两个吧,方便引入路由器的概念。

polls/views.py

# # Django的接口,默认已引入,这是一个渲染的函数,后面经常用。
from django.shortcuts import render
# 引入 HttpResponse 来处理HTTp响应
from django.shortcuts import HttpResponsedef index(request):return HttpResponse("<h1>Hello world!</h1>")def hello(request):return HttpResponse("<h1>Hello Django!</h1>")

  写了两个视图函数,我们需要把他显示在前端,但是有两个,我们改如何分别显示他们呢?
  路由器。

五、编写路由器

  类比于电脑前的路由器,电脑前的路由器是把局域网内的(WIFI信号内)的网络请求,打包成一个数据包发出去的,然后再把响应发回来。
  同理,我们配置下Django的路由,就可以让每个视图,各回各家,各找各妈了。

polls 目录下创建一个新的文件urls.py


# path 就是处理路径的一个模块
from django.urls import path# 引入我们自己写的视图函数,不引入的话路由器怎么知道改管理谁的视图呢?
from . import views# 配置路由规则,各回各家,各找各妈!
urlpatterns = [path('index', views.index, name='index'),path('hello', views.hello, name='hello'),
]

1、挂载路由

  路由管理我们写好了,但是这只是一个app的路由管理,整个项目是还需要一个路由管理的,所以我们需要将我们写的这个应用的路由文件挂载到项目的路由管理上去。

mysite/urls.py

"""mysite URL ConfigurationThe `urlpatterns` list routes URLs to views. For more information please see:https://docs.djangoproject.com/en/3.2/topics/http/urls/
Examples:
Function views1. Add an import:  from my_app import views2. Add a URL to urlpatterns:  path('', views.home, name='home')
Class-based views1. Add an import:  from other_app.views import Home2. Add a URL to urlpatterns:  path('', Home.as_view(), name='home')
Including another URLconf1. Import the include() function: from django.urls import include, path2. Add a URL to urlpatterns:  path('blog/', include('blog.urls'))
"""
# django的后台管理模块,默认已经引入
from django.contrib import admin
# 路径处理模块,默认已经引入path,我们需要引入一个include模块,因为我们要引入app自己的路由规则
from django.urls import path, includeurlpatterns = [path('admin/', admin.site.urls),# 引入polls应用的url路由配置文件。path('polls/', include('polls.urls')),
]

2、启动项目

python manage.py runserver

  这时候我们可以启动项目,查看下我们的路由和视图是否可以正常工作。按照我们编写的逻辑。
  访问http://127.0.0.1:8000/polls/index 会显示Hello world!,并且是一级标题
  访问http://127.0.0.1:8000/polls/hello 会显示Hello Django!,同样是一级标题
  很好,项目正常运行了!

六、编写模板

  从<h1></h1>一级标题可以正常显示我们知道,我们完全可以return一个HTML文档,当然我们最好把它分离出来,因为写在这个文件里不方便修改,也有点臃肿。
  在polls根目录下创建templates文件夹,然后在此目录创建一个index.html文件。

templates/index.html

<!doctype html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport"content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0"><meta http-equiv="X-UA-Compatible" content="ie=edge"><title>Document</title>
</head>
<body>
<h1>Hello Django!</h1>
</body>
</html>

更改视图函数

polls/views.py

# Django的接口,默认已引入,这是一个渲染的函数,后面经常用。
from django.shortcuts import render
# 引入 HttpResponse 来处理HTTp响应
from django.shortcuts import HttpResponsedef index(request):return HttpResponse("<h1>Hello world!</h1>")def hello(request):return render(request, 'index.html',context=None)

  测试,程序正常。
  因为我们这里用到了index.html文件,使用render函数更加方便。
  但有个小问题,就是我们的内容是写死在HTML文件的,我们有办法让HTML的文件跟着我们的程序改变吗,有的,就是Django的插值语法。

  我们把<h1>标签里的内容改成。

...
<h1>Hello {{name}}!</h1>
...

  name就是一个变量,随着变量值的不同,HTML就响应不同的内容了。
  在视图函数里加入name变量。

polls/views.py

# # Django的接口,默认已引入,这是一个渲染的函数,后面经常用。
from django.shortcuts import render
# 引入 HttpResponse 来处理HTTp响应
from django.shortcuts import HttpResponsedef index(request):return HttpResponse("<h1>Hello world!</h1>")def hello(request):name = "小孙同学"return render(request, 'index.html', context={'name': name})

  context就是变量和模板交接的东西。专业名称叫做上下文
  测试一下,我们可以写动态的数据啦!

七、写点有用的视图

  上面虽然写了两个视图,打通了前端,但是没有和后端交互。把我们写的视图注释掉,继续跟着官方文档写点有用的视图吧。

polls/views.py

# Django自带的渲染函数,默认已经引入
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, 'index.html', context)

templates/index.html

<!doctype html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport"content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0"><meta http-equiv="X-UA-Compatible" content="ie=edge"><title>Document</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>没有可用的投票。</p>
{% endif %}
</body>
</html>

  重启应用。
访问http://127.0.0.1:8000/polls/

访问http://127.0.0.1:8000/admin/为应用增加加几个投票。
访问http://127.0.0.1:8000/polls/正常显示

八、路由分发的进阶

  上面写了几个投票,他是一个超链接, href值指向的是这个投票对应的详情。所以我们需要定义一个新的视图函数detail(名字自拟)来显示详情。
polls/views.py

# Django自带的渲染函数,默认已经引入
from django.shortcuts import render
# 引入我们写的数据表
from .models import Questionfrom django.shortcuts import HttpResponse# 写了一个和后端交互的视图
def index(request):# 按照时间逆序排列,查询前五个数据表中存在的投票,存储为列表latest_question_list = Question.objects.order_by('-pub_date')[:5]# 上下文context = {'latest_question_list': latest_question_list}# 返回渲染好的页面return render(request, 'index.html', context)# 显示详情函数
def detail(request, question_id):return HttpResponse("你在看问题 %s。" % question_id)

  定义一个新的视图后,我们需要为这个视图配置url的规则。
  但是,按照上述的设计,每个详情都应该对应一个URl,那我们是不是要写好多URL
  可以是也可以不是,因为这些URL是有规律的,路由分发的路径可以用公式代替。

polls/urls.py

from django.urls import pathfrom . import viewsurlpatterns = [# ex: /polls/path('', views.index, name='index'),# ex: /polls/5/path('<int:question_id>/', views.detail, name='detail'),
]

  重启项目,点进去相应的问题,可以显示内容了,虽然这里只是显示问题几。

九、去除模板中的硬编码 URL

...
<a href="/polls/{{ question.id }}/">
...

  记得这行代码吧,就是写在index.html里的,这里有个问题,这个路径是写死的,一旦我们改了路由地址,我们还需要动模板里面的href值,这样不好。
  这时候path()函数的第三个参数就起作用了。

polls/urls.py

    path('<int:question_id>/', views.detail, name='detail'),

  把模板这样写

...
<a href="{% url 'detail' question.id %}">{{ question.question_text }}</a>
...

  但这样还有一个问题,我们的URL最终是给项目使用的,但一个项目里有多个应用,名字有重名怎么办,所以这就需要我们为应用加一个名字。

poll/urls.py

...
app_name = 'polls'
...

  把模板这样写

...
<a href="{% url 'polls:detail' question.id %}">{{ question.question_text }}</a>
...

十、显示详情

  当我们点进去一个投票后,可以进入该投票的详情页,然后对其进行选择,之前我们仅仅显示了你在看问题几,现在是时候该细化了。
  首先,我们在后台为这个投票加几个数据。然后在模板文件夹里创建一个模板detail.html,显示详情。

新建模板
detail.html

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><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>

更新视图
polls/views.py

# Django自带的渲染函数,默认已经引入
from django.shortcuts import get_object_or_404, render
# 引入我们写的数据表
from .models import Questionfrom django.shortcuts import HttpResponse# 写了一个和后端交互的视图
def index(request):# 按照时间逆序排列,查询前五个数据表中存在的投票,存储为列表latest_question_list = Question.objects.order_by('-pub_date')[:5]# 上下文context = {'latest_question_list': latest_question_list}# 返回渲染好的页面return render(request, 'index.html', context)# 显示详情函数
def detail(request, question_id):# 404异常处理question = get_object_or_404(Question, pk=question_id)return render(request, 'detail.html', {'question': question})

  404异常处理需要引用一个,get_object_or_404,emmm,雀食,多写异常处理是好事。
测试一下。

十一、编写表单

  我们已经写好的详情页需要显示的内容,但这毕竟是一个选择题,这样写只能展示,但用户没法选择,所以我们需要写一个表单。

detail.html

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>详情</title>
</head>
<body>
<form 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>{% endfor %}</fieldset><input type="submit" value="提交">
</form>
</body>
</html>

  运行项目,表单可以正常显示。

  但是这只是前端的表单,我们是需要提交数据到数据库的,目前的这个提交按钮形同虚设,所以我们需要定义一个新的视图函数,然后添加到表单的action属性上。这个视图函数负责接受表单里的数据,然后将其添加到数据库中。

polls/views.py

# Django自带的渲染函数,默认已经引入,404处理函数。
from django.shortcuts import get_object_or_404, render
# 引入我们写的数据表
from .models import *# 写了一个和后端交互的视图
def index(request):# 按照时间逆序排列,查询前五个数据表中存在的投票,存储为列表latest_question_list = Question.objects.order_by('-pub_date')[:5]# 上下文context = {'latest_question_list': latest_question_list}# 返回渲染好的页面return render(request, 'index.html', context)# 显示详情函数
def detail(request, question_id):# 404异常处理question = get_object_or_404(Question, pk=question_id)return render(request, 'detail.html', {'question': question})# 处理投票结果
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': "您没有选择任何一个选项。",})

为其配置url规则
polls/urls.py

...# ex: /polls/5/vote/path('<int:question_id>/vote/', views.vote, name='vote'),
...

  当我们选择了选项,下面就是显示投票结果了,所以我们还需要定义一个视图,来显示投票结果。

def results(request, question_id):question = get_object_or_404(Question, pk=question_id)return render(request, 'results.html', {'question': question})

  我们需要定义显示结果的模板文件。
results.html

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>答案</title>
</head>
<body>
<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 %}">再次投票?</a>
</body>
</html>

  为其匹配路由规则。
polls/urls.py

...# ex: /polls/5/results/path('<int:question_id>/results/', views.results, name='results'),
...

  当我们投完票后,我们就可以指定相应的路由地址来查看投票结果了。

  但是这样非常不智能,我们的需求是,当我们投完票后就可以自动跳转到相应的路由地址查看投票结果。
  我们需要在投完票后添加这个功能,所以我们需要更改vote这个视图函数来实现这个功能。
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):# Redisplay the question voting form.return render(request, 'detail.html', {'question': question,'error_message': "You didn't select a choice.",})else:selected_choice.votes += 1selected_choice.save()return HttpResponseRedirect(reverse('polls:results', args=(question.id,)))

  值得注意的是,因为我们这里引用了HttpResponseRedirect()reverse()函数,所以我们需要从相应的模块里引入他们。

from django.urls import reverse
from django.shortcuts import  HttpResponseRedirect

  到此,简易的投票功能就已经实现了,不谈及样式问题,官方还有一个优化,就是使用通用视图。

十二、通用视图

  改良可做可不做,下面的代码会少一点,但我觉得上面的代码更容易理解。

1、改良 URLconf

polls/urls.py

from django.urls import pathfrom . import viewsapp_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'),
]

  注意,第二个和第三个匹配准则中,路径字符串中匹配模式的名称已经由 <question_id>改为 <pk>

2、改良视图

  在视图中,我们是通过get方法获取数据表中的数据然后赋值给一个变量(对象),但我们也可以直接把数据表搬到视图中,这应该就是所谓的通用视图吧。
  删除旧的 index, detail, 和 results 视图,并用 Django 的通用视图代替。
polls/urls.py

from django.http import HttpResponseRedirect
from django.shortcuts import get_object_or_404, render
from django.urls import reverse
from django.views import genericfrom .models import Choice, Questionclass IndexView(generic.ListView):template_name = '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 = Questiontemplate_name = 'detail.html'class ResultsView(generic.DetailView):model = Questiontemplate_name = 'results.html'def vote(request, question_id):... # 和之前一样,不用改。

First Django APP相关推荐

  1. [Django]APP级别的静态文件处理

    2019独角兽企业重金招聘Python工程师标准>>> 转载自 limodou的学习记录 [Django]APP级别的静态文件处理 静态文件在 django 中并不是非常简单的事情. ...

  2. django app注册过程

    django app注册过程 相关知识 sys.modules[__name__]获取本模块 collections是Python内建的一个集合模块,提供了许多有用的集合类. namedtuple n ...

  3. Django - app

    1.app目录 migrations:数据库操作的记录(只记录修改表结构的记录); __init__文件:python2中必须填加,python3中无要求,可以不添加: admin:django为我们 ...

  4. django app中扩展users表

    app models中编写新的User 1 # _*_ coding:utf-8 _*_2 from __future__ import unicode_literals34 from django. ...

  5. django app服务器搭建

    首先是在ubuntu 16.04下进行搭建的,开发工具选用aptana,python选用python3.5,django选用最新的版本进行搭建,最后搭建完毕后发现数据库配置一直有问题,所以最后直接在w ...

  6. Heroku 部署 Django APP

    什么是Heroku? Heroku是一个支持多种编程语言的云平台, 可以理解为一个免费的托管服务器.开发者开发完app,使用Git程序推送到Heroku的Git服务器上,这样其他人就可以通过网址来访问 ...

  7. Django|编写第一个Django程序|Writting your first Django app|Windows环境

    目录 1.Django官网:The web framework for perfectionists with deadlines | Django 2.django的安装 一.未安装 二.已安装dj ...

  8. 【0】依照Django官网:实现第一个django app 安装必要的工具/模块

    1.环境配置: (1)Install Setuptools¶ To install Python packages on your computer, Setuptools is needed. Do ...

  9. 【AMAD】django-filer -- 一个管理文件和图片的django app

    动机 简介 个人评分 动机 django-filer1可以让你像一些云存储一样使用WEB UI控制你的文件. 简介 下面是前端图片:   个人评分 类型 评分 实用性 ⭐️⭐️⭐️⭐️ 易用性 ⭐ ...

最新文章

  1. java中字节输入流和输出流的简单使用例子
  2. cad等比例缩放快捷键_「CAD」利用块对图形进行非等比例缩放
  3. SES机箱管理知识回顾(四)之SES Over SAS
  4. python朋友圈为什么这么火-看我如何用Python发一个高逼格的朋友圈
  5. DataTable的计算功能(转)
  6. vim匹配特定的行并删除它
  7. 【转】1.A(译).NET4.X 并行任务中Task.Start()的FAQ
  8. idea cloud bootstrap是啥_application.yml与bootstrap.yml的区别
  9. PS将两张图像合成为一张
  10. 3、InterruptedException
  11. 优化CUDA数据传输
  12. java 利用同步工具类控制线程
  13. java常用工具类封装
  14. 西威变频器使用说明书_西威变频器说明书
  15. 如何改变报表在页面显示的大小和位置?
  16. (目录)微气候模型ENVI-met模拟的基本使用教程
  17. unity 音频可视化
  18. 淘宝评论接口调用展示
  19. Java实现手写数字的识别(BP神经网络的运用)
  20. Java数据结构-树状数组

热门文章

  1. python量化投资实战-股票实盘分析
  2. tv3描述文件代理服务器,tvos14描述文件-tvos14beta描述文件更新官网 v1.0预约_手机乐园...
  3. contenttype类型php文件上传,php aws 文件上传设置content_type
  4. Zookeeper报错:Unable to read additional data from server sessionid 0x
  5. 风控体系及政策设计介绍
  6. 浅谈共享软件如何不被暴力蹂躏
  7. mysql实现vpd_一种存储的VPD信息访问方法及系统与流程
  8. 数据挖掘技术特写(转)
  9. 算法:“最大公约数” 和 “最小公倍数”
  10. 毕业设计 stm32地下井盖管道安全监控系统 - 物联网 单片机