Django 是 Python 的 一款 Web 开发框架,另外还有 Tornado,Flask,Twisted。为什么我要选择学 Django?原因很简单,上家公司来了个网易的测开,就是用 Django 开发的测试平台。

这位测开没多久就离职去腾讯了,我啥也没学到,看了他的代码,很多是写的 Vue 代码,哭啊。

Django 诞生于 2003 年的秋天,由 Lawrence Journal-World 报纸的程序员 Adrian Holovaty 和 Simon Willison 编写而成。新闻编辑室的开发节奏是非常快的,正因如此,Django 相比于其他框架的特点就是短、平、快。这也符合 Python 的风格。时至今日,Django 已经发展到了 3.1.3 版本。本系列将基于这一版本的官方文档,边学习边实践,整理成文,分享给大家。

Django 系列不是教程,而是学习笔记、心得体会、踩坑记录,内容编排上可能会有点乱。需要看教程请阅读官方文档,水平有限,实在抱歉。

Django 遵循 MVC 架构模式,所以接下来就看看如何使用 Django 完成 Web 开发。特别注意,本文的内容不具有实操性,看看即可。

定义 model

model 是数据模型,定义了数据库的表和字段。

例如:

  1. from django.db import models
  2. class Reporter(models.Model):
  3. full_name = models.CharField(max_length=70)
  4. def __str__(self):
  5. return self.full_name
  6. class Article(models.Model):
  7. pub_date = models.DateField()
  8. headline = models.CharField(max_length=200)
  9. content = models.TextField()
  10. reporter = models.ForeignKey(Reporter, on_delete=models.CASCADE)
  11. def __str__(self):
  12. return self.headline

通过类和属性,分别定义了 2 张表 Reporter 和 Article,以及它们的字段(Reporter 1 个字段,Article 4 个字段)。

这其实就是 ORM,即 Object Relational Mapping,对象关系映射,把程序代码中的对象映射到关系型数据库中,不用写 SQL,就可以直接操作数据了。ORM 实现了数据持久化。我们都知道程序是运行在内存中的,跑完就没了。为了把数据保存下来,就需要使用 ORM 技术把内存中的数据(程序对象)存到关系型数据库中,进而转移到磁盘上。Django 自带了一个 ORM,开箱即用。

数据迁移

使用 2 条命令,就可以把 model 迁移到数据库中:

  1. $ python manage.py makemigrations
  2. $ python manage.py migrate

执行完成后,就会在数据库中按照 model 定义的表名、字段名、约束条件等,创建表结构。

数据操作

接着就可以在程序中写代码操作数据了。为了直观看到结果,这里以命令行形式进行演示:

  1. # 导入已创建的 models
  2. >>> from news.models import Article, Reporter
  3. # 查询表 Reporter 为空
  4. >>> Reporter.objects.all()
  5. <QuerySet []>
  6. # 实例化对象,创建 1 条数据,表 Reporter 的字段是 full_name
  7. >>> r = Reporter(full_name='John Smith')
  8. # 必须显式调用 save() 函数,才会真正写数据到数据库
  9. >>> r.save()
  10. # 保存后就有 id 了
  11. >>> r.id
  12. 1
  13. # 查询表 Reporter 有数据了
  14. >>> Reporter.objects.all()
  15. <QuerySet [<Reporter: John Smith>]>
  16. # 访问对象属性
  17. >>> r.full_name
  18. 'John Smith'
  19. # Django 提供了 get() 函数来支持更多查询方式
  20. >>> Reporter.objects.get(id=1)
  21. <Reporter: John Smith>
  22. >>> Reporter.objects.get(full_name__startswith='John')
  23. <Reporter: John Smith>
  24. >>> Reporter.objects.get(full_name__contains='mith')
  25. <Reporter: John Smith>
  26. >>> Reporter.objects.get(id=2)
  27. Traceback (most recent call last):
  28. ...
  29. DoesNotExist: Reporter matching query does not exist.
  30. # 给表 Article 添加 1 条数据
  31. # 有 4 个字段 pub_date, headline, content, reporter
  32. # reporter=r,用 Reporter 对象赋值
  33. >>> from datetime import date
  34. >>> a = Article(pub_date=date.today(), headline='Django is cool',
  35. ... content='Yeah.', reporter=r)
  36. >>> a.save()
  37. # 表 Article 也有数据了
  38. >>> Article.objects.all()
  39. <QuerySet [<Article: Django is cool>]>
  40. # a.reporter 可以赋值给 r
  41. >>> r = a.reporter
  42. >>> r.full_name
  43. 'John Smith'
  44. # r 也可以访问 Article
  45. >>> r.article_set.all()
  46. <QuerySet [<Article: Django is cool>]>
  47. # 可以借助 filter() 函数按条件过滤数据
  48. >>> Article.objects.filter(reporter__full_name__startswith='John')
  49. <QuerySet [<Article: Django is cool>]>
  50. # 赋值后调用 save() 函数更新数据
  51. >>> r.full_name = 'Billy Goat'
  52. >>> r.save()
  53. # 使用 delete() 函数删除对象,数据库这条数据也会被删除
  54. >>> r.delete()

自带 Admin 后台

一般不会用它。

设计 URLs

我们是通过 URL 发送请求的,服务端程序做处理,处理的函数叫做回调函数。Django 在 urls.py 文件中编写 URL 和回调函数的映射关系。例如:

  1. from django.urls import path
  2. from . import views
  3. urlpatterns = [
  4. path('articles/<int:year>/', views.year_archive),
  5. path('articles/<int:year>/<int:month>/', views.month_archive),
  6. path('articles/<int:year>/<int:month>/<int:pk>/', views.article_detail),
  7. ]

path() 的第一参数是 URL,这里使用了 <> 参数标签来获取 URL 中的数据,然后传入到回调函数中。第二个参数是回调函数,位于 views 中。

如果请求 URL “/articles/2005/05/39323/”,Django 就会获取参数值后调用回调函数:

  1. news.views.article_detail(request, year=2005, month=5, pk=39323)

Django 在启动加载时就会把这些 path 编译为正则表达式,查找速度飞快。匹配到第一个后就会停止查找,调用回调函数。如果找完了都没有,就会调用 404 这个特殊 view,表示没找到。

编写 views

在 views 中编写回调函数。每个回调函数只做 1 件事,要么返回包含响应的 HttpResponse 对象,要么抛出异常,如 Http404 。例如:

  1. from django.shortcuts import render
  2. from .models import Article
  3. def year_archive(request, year):
  4. a_list = Article.objects.filter(pub_date__year=year)
  5. context = {'year': year, 'article_list': a_list}
  6. return render(request, 'news/year_archive.html', context)

return render() 函数会返回一个 HttpResponse 对象。

注意,这个例子用到的是 Django 自带的模板引擎。所谓模板引擎,就是前端的 HTML 模板,里面的数据可以写成变量,从后端动态获取。除了内置的这个,还有其他模板引擎如 Thymeleaf、FreeMarker 等。不过这些使用都很少了。现在流行前后端分离,后端不需要写 HTML,只提供 RESTful 接口就可以了。说到 RESTful,就不得不提另外一个 Django 的衍生框架 DRF(Django REST Framework)。一步一步来,先学好了 Django,才能更好理解 DRF。

内置模板引擎

暂时不做介绍。

小结

本文以 Web 后台为例,讲解了从 model,到 ORM,到数据操作,到 URL 映射,到 views 回调函数的编写链路。实际操作会复杂得多。以前学其他框架有点懵,写这篇文章,倒是让我明白了 MVC 这一套是这么一回事。

参考资料:

https://docs.djangoproject.com/en/3.1/intro/overview/

Django匆匆一眼却解答了多年疑惑的更多相关文章

  1. Django搭建示例项目实战与避坑细节

    Django 开发项目是很快的,有多快?看完本篇文章,你就知道了. 安装 Django 前提条件:已安装 Python. Django 使用 pip 命令直接就可以安装: pip install dj ...

  2. 尝试解答java内存问题

    在园子中看见了这个园友的问题,高手指点一下,关于编写Java程序让Jvm崩溃,恰巧这两天看了点相关的东西,也尝试了一下,下面是仁兄提出的第一个疑问,我来复现一下: package jvm; publi ...

  3. 推翻自己和过往,重学自定义View

    http://blog.csdn.net/lfdfhl/article/details/51671038 深入探讨Android异步精髓Handler 站在源码的肩膀上全解Scroller工作机制 A ...

  4. Tengine 如何查找 server 块

    概述 本文的目标读者是Tengine/Nginx 研发或者运维同学,如果自己对这块逻辑非常清楚,那可以略过,如果在配置或者开发 Tengine/Nginx 过程中,有如下疑问的同学,本文或许能解答你多 ...

  5. 单独编译使用WebRTC的音频处理模块

    块,每块个点,(12*64=768采样)即AEC-PC仅能处理48ms的单声道16kHz延迟的数据,而 - 加载编译好的NS模块动态库 接下来只需要按照 此文 的描述在 android 的JAVA代码 ...

  6. Autofac - 装配

    从容器中的可用服务中, 选取一个构造函数来创造对象, 这个过程就是自动装配. 一.选择构造函数 默认情况下, autofac会使用无参构造函数, 去创建对象. 我将Person类稍微修改了下. pub ...

  7. Linux 磁盘自检介绍

    在Linux系统中,有时候重启会耗费非常长的时间,如果你进一步检查细节,就会发现绝大部分时间都耗费在磁盘自检(fsck)上了,有时候遇到时间比较紧急的情况,磁盘自检耗费的时间非常长,真的是让人心焦火急 ...

  8. springMVC 配置CharacterEncodingFilter之后不起效果

    最近开始自学springMVC框架,遇到中文乱码这一经典问题,记录下解决过程,以便后续忘记 web.xml 里过滤器配置如下: <?xml version="1.0" enc ...

  9. dwarf格式解析

    debug_line中包含的是地址和源文件行之间的关系 我今天想搞清楚的是文件的C代码和汇编代码之间的关系: 对这块之前一直是迷迷糊糊的,发现这个问题已经严重影响到bug的定位了. 之前感觉C和汇编不 ...

随机推荐

  1. [Luogu P2278] [HNOI2003]操作系统

    题面 传送门:https://www.luogu.org/problemnew/show/P2278 Solutiton 挺简单的一道模拟题,拿堆模拟一下题目意思就好 堆中有两个关键字,分别是优先级和 ...

  2. MySQL索引分析及使用

    一.索引介绍 1.1.什么是索引? 一般的应用系统,读写比例在10:1左右,而且插入操作和一般的更新操作很少出现性能问题,在生产环境中,我们遇到最多的,也是最容易出问题的,还是一些复杂的查询操作,因此 ...

  3. PASS模型-第一周个人总结

    目录 PASS模型-第一周个人报告 1.个人任务 2.个人工作内容 2.1 登陆界面 2.2 信息采集 2.3 视觉搜索 3.个人小结 3.1 收获 3.2 优化 PASS模型-第一周个人报告 博客班 ...

  4. 通俗易懂浅谈理解ES6类this不同指向问题

    1. class Btn{ //定义的一个类 constructor(id){ // constructor是一个构造函数,是一个默认方法,通过 new 命令创建对象实例时,自动调用该方法.一个类必须 ...

  5. CF1295E Permutation Separation

    线段树 难得把E想出来,写出来,但却没有调出来(再给我5分钟),我的紫名啊,我一场上紫的大好机会啊 首先考虑是否能将$k$在$1$--$n-1$的每一个的最小代价都求出来 因为$k$从$i$到$i-1 ...

  6. learning to Estimate 3D Hand Pose from Single RGB Images论文理解

    持续更新...... 概括:以往很多论文借助深度信息将2D上升到3D,这篇论文则是想要用网络训练代替深度数据(设备成本比较高),提高他的泛性,诠释了只要合成数据集足够大和网络足够强,我就可以不用深度信 ...

  7. tensorflow的广播机制

    TensorFlow支持广播机制(Broadcast) TensorFlow支持广播机制(Broadcast),可以广播元素间操作(elementwise operations).正常情况下,当你想要 ...

  8. 面向初学者的Python爬虫程序教程之动态网页抓取

    目的是对所有注释进行爬网. 下面列出了已爬网链接.如果您使用AJAX加载动态网页,则有两种方式对其进行爬网. 分别介绍了两种方法:(如果对代码有任何疑问,请提出改进建议)解析真实地址爬网示例是参考链接 ...

  9. linux中配置yum文件

    yum简介:yum的宗旨是自动化地升级,安装/移除rpm包,收集rpm包的相关信息,检查依赖性并自动提示用户解决. yum的关键之处是要有可靠的repository,顾名思义,这是软件的仓库,它可以是 ...

  10. python-基础入门-1

    Python的打印为   print,等价于c语言的printf 1 print "hello again" 就能打印出hello again,简简单单,就这么一句. 我用的vsc ...