Python Django开发实战(视频讲解版)(txt+pdf+epub+mobi电子书下载)


发布时间:2020-08-04 12:47:39

点击下载

作者:张虎

出版社:人民邮电出版社有限公司

格式: AZW3, DOCX, EPUB, MOBI, PDF, TXT

Python Django开发实战(视频讲解版)

Python Django开发实战(视频讲解版)试读:

前言

近年来,由于Python语言具有简单、高效的特性,其应用的热度越来越高。同时,Python也逐渐地应用到Web开发中。基于Python的Web开发框架也越来越多,其中Django以开发迅速、代码结构清晰以及功能齐全等优点,成为最受用户青睐的Web开发框架。

Django是一个全能型框架,内置了很多功能模块,“开箱即用”的同时也解决了Web开发中的各种难点问题,让开发者能够更加专注地编写业务逻辑。但同时,也因为Django功能覆盖全面、框架庞大,可能会让用户在学习使用的过程中产生困惑。所以,本书对Django最为核心且常用的模块进行了梳理,以应用结合实现原理的模式解答了两个问题,即怎样使用Django与Django是怎样完成工作的。

本书涉及Django应用环境搭建、应用实现与原理分析、应用部署三个主题,其中应用实现与原理分析是本书的核心内容,也是篇幅最多的内容。

全书以一个BBS应用为主线,使用Django内置的各个核心模块逐渐完善其功能,并在完成各个功能点之后,分析其实现原理。读者通过学习本书不仅能够学会开发Django应用,而且能够在理解工作原理的基础上更好地应用并解决问题。

全书共14章,第1章介绍了Django的产生背景、版本迭代发布过程以及Django的内置功能模块,第2章介绍了开发环境的配置,第3章对搭建Django项目框架的过程进行了介绍,第4章至第13章逐步完善BBS应用的功能并分析其实现原理,第14章介绍了Django项目的部署。

本书提供了详细的视频讲解,具体内容可通过人邮学院(www.rymooc.com)平台进行学习,读者可扫描二维码查看本书视频课程页面。

2018年6月,人民邮电出版社刘博老师邀请我编写一本关于Django开发方面的图书。我非常感谢刘博老师给予的这个机会,当然也就不敢怠慢。我自此开始查阅资料、整理笔记、完成样章,并最终完成初稿。这其中,特别感谢刘博老师对于书写、内容等方面的建议,使我顺利地完成本书的编写。

在此要感谢我的家人,编写这本书用去了我所有的周末与节假日时间,正是你们的陪伴、支持与照顾才让我以最好的状态去完成它。

在写作过程中,感谢各位朋友的帮助与支持,感谢高军、华成婷、闫俊东、罗蒙震锋、唐爽硕、赵甜芳、张旭、左海洋、程皓洁、欧阳生、汪奎伟、杨燕海、陶磊、赵虹杰等好友,正是有了和你们讨论问题与寻求解答的过程,才让这本书的质量不断提升,使我能够给读者奉上更好的作品。

由于时间仓促,加之个人水平有限,书中难免存在不足之处,敬请广大读者批评指正。张虎2019年7月第1章 初识Django框架

Django是一个开放源代码的Web应用框架,使用Python语言编写完成。由于Python语言是跨平台的,所以,不论操作系统是Windows、Linux还是macOS X,都可以开发Django应用。Web框架是一套组件,提供通用的设计模式,能够最大程度地降低开发Web站点的难度。Django的设计目标就是使开发复杂的、数据库驱动的网站变得简单,注重组件的可重用性与可插拔性。本章我们就来看一看Django是怎么被发明出来的,它能够做什么,有哪些组件以及各自的功能特性。1.1 Django的产生背景1.1.1 Django的创建背景

假设现在没有Django,我们要开发一个Web站点,需要做哪些工作,写哪些组件去完成它呢?通常需要做下面的几件事。(1)构建用户账户体系,实现Web站点的登录与注册功能。(2)定义数据表模型及实现访问功能。(3)编写业务逻辑实现站点功能。(4)实现后台管理功能。(5)路由模型实现功能请求映射。

以上这些就是实现一个基本的Web站点需要做的工作。A站点做完之后,我们可能还需要去做B站点,但是,通常不同的站点只是步骤(3)的业务逻辑不同,其他的功能需求是类似的,甚至是完全一样的。那么能不能把通用的组件或者模块组合在一起,提供给开发Web站点的人使用呢?后来就出现了Web框架的概念,这就是Django产生的根本原因。

Django最初是被开发用来管理劳伦斯出版集团旗下的一些以新闻内容为主的网站的。2003年秋天,Lawrence Journal-World报社的Web开发者艾德里安·胡卢瓦提(Adrian Holovaty)和西蒙·威利森(Simon Willison)开始使用Python语言去构建应用,他们所在的World Online小组搭建并维护当地的几个新闻站点。新闻界的快节奏促使团队不断提高其产品开发速度,于是Simon和Adrian想办法构建出一个能够节省开发时间的框架,将可重用的组件组合在一起,不必做重复的工作,就这样,Django诞生了。之后,World Online小组的成员雅各布·卡普兰-莫斯(Jacob Kaplan-Moss)将这个框架发布为一个开源软件。

经过数年发展,Django有了数以万计的用户和贡献者,现在的Django毫无疑问已经成为Python开发中最流行的Web框架。1.1.2 Django的版本发布过程

Django遵守BSD(Berkeley Software Distribution,伯克利软件发行版)版权,初次发布于2005年7月,并于2008年9月发布了第一个正式版本1.0。

从正式版1.0之后,Django的版本发布过程如下。(1)功能版本:版本号定义为A.B、A.B+1等,大约每8个月发布一次,每个版本均包括新功能以及对现有功能的改进。(2)补丁版本:版本号定义为A.B.C、A.B.C+1等,用来修复bug或者是安全问题,补丁版本是100%兼容相关的功能版本的,所以,除了由于安全问题或者是可能造成数据丢失的情况之外,都应该升级到最新的补丁版本。(3)LTS版本:即长期支持的版本,某些功能版本会被指定为LTS版本,如1.8LTS版本,这类版本的安全更新时长至少需要3年。

值得注意的是,Django最后一个支持Python 2.7的版本是1.11LTS,在本书写作之际,Django最新的功能版本是2.0,如果想使用最新版本的话,需要选择Python 3。1.2 MTV设计模式1.2.1 熟悉的MVC设计模式

Web服务器开发领域里有着著名的MVC设计模式:数据存取逻辑、业务逻辑和表现逻辑。把它们3个组合在一起的时候,就构成了Model-View-Controller(MVC)。

在这个模式中,Model代表的是数据存取层,是对数据实体的定义和对数据的增删改查操作;View代表的是视图层,即系统中选择显示什么和怎么显示的部分;Controller代表的是控制层,它负责根据从View中输入的指令检索Model中的数据,再以一定的逻辑产生最终的结果输出。MVC设计模式的交互过程如图1-1所示。图1-1 MVC设计模式的交互过程

MVC的3层之间紧密相连,但是又相互独立。每一层的修改都不会影响其他层,每一层都提供了各自独立的接口供其他层调用,这种模块化的开发极大地降低了代码之间的耦合,也增加了模块的可重用性。1.2.2 Django的MTV设计模式

Django框架的设计模式借鉴了经典的MVC思想,将交互过程分成了3层,主要目的是降低各个模块之间的耦合。

Django框架将交互过程拆分为Model(模型)、Template(模板)和View(视图),即MTV设计模式,主要包括以下内容。(1)M(Model):数据存取层,这一层处理所有与数据相关的事务,提供在数据库中管理(添加、修改、删除)和查询记录的机制。(2)T(Template):表现层,处理页面的显示,即所有与表现相关的决定都由这一层去处理。(3)V(View):业务逻辑层,负责处理业务逻辑,会在适当的时候将Model与Template组合在一起,通常被认为是联通M与T的桥梁。

从概念上可以看出,Django也是一个MVC框架,但是在Django中,C(Controller)是由框架自行处理的,它由框架的URLConf来实现,其机制是使用正则表达式匹配URL,再去调用合适的Python函数。所以,Django更关心的是M、T和V。Django的MTV设计模式的交互过程如图1-2所示。图1-2 Django的MTV设计模式的交互过程1.3 Django提供的主要功能模块1.3.1 Django中的ORM

ORM(Object Relational Mapping,对象关系映射)把对象与数据库中的表关联起来,对象的属性映射到表的各个字段,同时,还把对表的操作对应到对对象的操作,实现了对象到SQL、SQL到对象的过程转换。

Django为ORM提供了强大的支持,适配了多种常用的数据库,如PostgreSQL、MySQL、Oracle等。Django把表模型定义为Model,其定义过程非常简单,只需要继承自django.db.models中的Model类就可以了,Model类中的每一个属性都能映射到表的对应字段。

针对数据库中提供的字段类型,Django ORM都有对应的*Filed来表达,如CharField、TextField、DateField等。对于数据库表的增删改查操作,Django也都提供了简单且优雅的API。

假设系统中有一张User表,存在name和password两个字符型的字段,那么,利用Django的ORM实现User Model的定义如下:

检索系统中所有的User记录:

检索系统中name含有a的所有User记录:

创建name是b、password是c的User记录:

除了这些基本的功能之外,Django还提供了分组和聚合查询、F查询与Q查询、通过外键关联的多表查询等高级功能。1.3.2 用户模块与权限系统

设计开发任何一个站点都需要有用户的概念,用户登录、注销过程,用户浏览了哪些页面,订阅了哪些消息等功能,都需要由用户系统来实现。设计一个好的、功能完善的用户系统往往是比较困难的,如果之前没有这方面的经验,从零做起,那又会增加一些难度。Django作为一个功能完善的Web框架当然会考虑到这一点,利用Django提供的用户模块,能够快速实现与用户相关的基本功能。有了用户的概念,是不是要对用户做一些区分呢?哪些用户是普通角色,哪些用户是管理员角色,又有哪些用户是超级管理员角色?基于这些问题,Django提供了权限系统作为解决方案。

Django的用户模块定义在auth应用中,主要提供的功能包括以下内容。(1)实现用户与用户组,维护用户与用户组的关系。(2)权限系统的逻辑设计。(3)对每个Model添加增删改的权限。(4)用户与用户组的权限定义。(5)用户鉴权与登录功能。

除了实现以上功能外,Django还提供了一些与登录、注销、权限验证等功能相关的函数与装饰方法。1.3.3 Admin后台管理系统

通常,对于Web站点上的内容会有管理员修改数据的需求,但是直接在Shell上或者是数据库上进行修改不仅麻烦,而且容易误操作造成数据状态不一致。这就需要针对数据存储表构建后台管理系统。例如,对于博客或者BBS这样的Web站点,管理员可以从后台修改或者删除不合规的帖子,或者是进行发布营销话题等操作。这样的管理系统功能和实现上往往比较简单,但是,如果这样的需求很多,需要对多个表做数据管理,就会给开发人员增加很多重复的工作量。

Django提供了Admin Web后台管理系统来解决这个问题,它是Django的一个非常出色的功能。新建项目系统之后,几乎不用做任何配置,Django就已经设置好了后台管理的功能。如图1-3所示,新创建项目后,Django就提供了User和Group的管理后台。图1-3 Admin管理后台

Django原生的Admin管理界面并没有做太多展示上的修饰,但是,其功能非常强大,而且可以利用Model Admin实现个性化定制,例如,针对字段值的过滤功能、搜索功能、排序功能,针对数据表字段的展示顺序规则定义功能、字段归类功能等。

当然,Django已经非常成熟了,很多社区和第三方开发者给Django做了很多有用的插件,例如,用户想让Admin界面更加美观,可以使用django-admin-bootstrap插件自行修改配置。1.3.4 视图

Django视图是MTV设计模式中的V,它在Django中的体现是一个Python函数或者类,接收Web请求并返回Web响应。视图返回的响应可以是HTML文档,可以是一个重定向,也可以是一个Exce l文档等。下面是一个简单的视图函数:

3行简单的代码对应3个部分。(1)从django.http模块中引入HttpResponse,从名字可以看出,它是视图的响应类型。(2)定义了一个名字为hello_django的Python函数,同时,它也是一个视图函数。Django规定,视图函数至少需要有一个参数,且第一个参数是django.http.HttpRequest类型的对象,它携带了Web请求的所有信息,按照约定,称之为request。这里需要知道,函数的名字并不被Django所关心,通常的做法是将函数名称对应到实现的具体功能上。(3)视图返回文本响应内容,它是一个HttpResponse类型的对象。

虽然这个视图只包含3行代码,但是,已经能够完整地展示Django的视图实现形态了。Django收到请求之后,首先创建携带有请求信息的HttpRequest对象,然后根据规则选择加载对应的视图,将HttpRequest对象作为第一个参数传递到视图中,视图执行处理逻辑,最终返回HttpResponse对象响应。1.3.5 模板系统

hello_django这个视图函数虽然能够正常工作,但是,把HTML硬编码到Python代码中显然不是一个好的实现方案,其主要的原因如下。(1)HTML代码主要实现站点的展现形式,且这种展现形式往往是需要经常修改的,如果直接硬编码到代码中,则对HTML的修改都必须要修改Python代码,而实际的业务逻辑并没有发生改变。(2)业务实现上的Python代码和HTML代码并不存在交集,将它们耦合在视图中,会增加系统的复杂度,且维护起来会更加困难。

基于以上的两点原因,Django提供了模板系统用于将页面设计的HTML代码和用于逻辑处理的Python代码分离开来。利用模板系统,重新实现hello_django视图函数,需要添加一个HTML文件,即he llo.html,内容如下:

视图函数修改为:

这样,利用模板系统就实现了数据与逻辑的分离。即使将来Hello Django的展现形式发生变化,也不会影响视图函数,从而解耦了业务处理逻辑与数据展现样式。1.3.6 优雅的表单系统Form

每一个Web站点上都有许多表单用于提交用户输入的信息,例如Web站点的登录界面,它需要用户输入用户名和密码,之后提交登录,这就是一个登录表单。处理表单的过程往往会比较复杂,且不同表单的处理过程又是相似的。

不同类型的数据项在表单中渲染成HTML向用户展示,用户可以在表单中编辑并提交数据到后端服务器,服务逻辑对数据进行验证,进行后续的处理或者提示用户输入数据有误,这通常是一个表单的完整执行流程。使用Django提供的表单系统可以将上述过程大大简化,编写的代码也会更加优雅。

Django表单系统的核心是Form类,提供了以下4个主要的功能。(1)自动生成HTML表单元素。(2)检查表单数据的合法性。(3)对不合法的表单数据进行回显,并提示错误。(4)将表单数据转换为对应的Python数据类型。

假如要实现一个用户登录的表单,需要用户输入用户名和密码并提交验证,利用Django的表单系统可以按以下的步骤进行操作。

首先,创建Form对象,定义表单的两个数据字段:

其次,创建模板文件login.html,对应{{form}},Django通过表单系统完成数据项的渲染与绑定:

最后,创建视图完成登录处理逻辑:

可以看到,利用Django提供的表单系统,将原本复杂的工作变得相当简单,只需要围绕核心的Form对象就完成了表单的主体功能。1.3.7 信号机制

Django对信号机制的解释是:在框架的不同位置传递特定的消息给应用程序执行预定的操作。它是一种观察者模式,或者叫作发布-订阅模式。即当系统中有event(事件)发生,一组senders(发送者)将signals(信号)发送给一组receivers(接收者),receivers再去执行预定的操作。

Django自身预定义了很多信号,例如关于Model的执行动作信号、关于Http请求的执行动作信号,使用起来都非常简单,这里以Http请求到来的时候触发信号为例说明信号的各个元素。

首先,实现消息接收者receiver,打印Request Coming:

接着,将信号绑定到receiver上面(也可以使用装饰器实现绑定):

最后,等待Http请求到来,触发receiver的执行。如果框架预定义的信号不能满足需求,还可以实现自定义的信号。需要注意的是,Django信号机制的执行是同步的,所以,耗时的任务不可使用信号机制。1.3.8 路由系统

从MTV的设计模式中可以看到,用户向Web站点发送请求(对应到一个URL),首先会到达“对应的”视图,那么,这里的视图是怎么对应的呢?这就是Django路由系统的作用。

Django利用URLconf构建起URL模式与视图函数之间的映射关系,即利用Django的特定配置方式,设定好哪个URL可以去执行哪一段Python代码。Django路由系统配置的核心是path,它的基本配置格式如下:

path有4个参数,其中route是标识URL的正则表达式,view代表视图函数,这两个参数是必填字段;kwargs标识以字典的形式传递给视图的默认参数,name是给route起一个名字,用于反向解析,这两个参数都是可选的。

根据路由的匹配模式,可以把Django的URL映射模型分为3类。(1)固定URL映射:即一个固定不变的URL映射到一个视图函数,例如/bbs/对应于BBS站点的主页:path('bbs/',views.bbs)。(2)动态URL映射:即URL可以根据传递的参数实现动态构造,例如/bbs/1/和/bbs/2/分别展示BBS站点的第一页和第二页:path('bbs/',views.bbs_list)。(3)两级(多级)URL映射:如果一个项目下面有很多App,如果将每一个App的URL映射关系都维护在一处,显然不够灵活,Django提供了可以根据不同的App来对URL进行归类的include方法,例如path('topic/',include('topic.urls'))将所有'topic/'的请求都交给topic这个App下面的urls去处理。

Django的路由系统使用简洁、容易理解的路由语法,大大降低了学习配置URL的门槛。同时,在Django 2.0中增加了很多优秀的特性,例如,支持从URL中处理类型转换,利用Path Converters实现公共的正则表达式等。1.3.9 中间件

中间件是一个插件系统,嵌入在Django的Request和Response之间执行,可以对输入和输出内容做出修改。中间件是业务无关的技术类组件,是用来定义处理所有请求和响应的通用处理架构。

中间件就是一个普通的Python类对象,其中定义了一些函数在视图执行的前后调用。这些函数被称作钩子函数,且名称固定。(1)process_request:它在请求到来的时候调用。(2)process_view:它在对应的视图函数执行之前调用。(3)process_exception:它在视图函数抛出异常的时候调用。(4)process_template_response:它在视图函数有响应,且响应对象包含render方法时调用。(5)process_response:它在返回响应之前调用。

除了单个中间件执行的生命周期,Django也规定了中间件的执行顺序与配置的关系,配置越靠前的中间件越先被执行,从上到下顺序地执行每一个中间件,返回的时候正好相反,按照各个中间件配置的顺序逆序执行,执行过程如图1-4所示。图1-4 中间件执行过程

中间件将特定的业务处理逻辑和通用服务解耦,作为一个可插拔的组件对外提供服务。Django自身定义了许多有用的中间件,当然,也可以按照Django的接口约束实现自定义的中间件。1.3.10 缓存系统

有时访问Web站点的某一个服务会发现执行比较慢,这种情况发生的原因可能是背后有复杂的计算逻辑,也可能是访问数据库系统或者文件系统造成的I/O延迟等。通常提高Web站点执行效率的方法是使用缓存,将经常被用户访问的页面结果保存下来,用户再次访问时只需要返回缓存的结果即可,而不会再次执行计算等类似耗时的操作。

Django提供一个稳健的缓存系统,实现了不同级别的缓存粒度:可以缓存单个视图的结果输出,缓存难以生成的片段,或者是缓存整个网站。同时,Django还支持多种缓存类型,例如Memcached、数据库、文件系统等,可以根据自己的需要开启一种或者多种缓存类型。

在Django中使用缓存是非常简单的,例如,要缓存一个视图的结果:

只比原来的视图函数多了一个cache_page装饰器,就可以将视图的结果缓存15分钟(装饰器参数是秒),其代码非常优雅且容易理解。

Django被称为“完美主义者的最终框架”,因为它允许开发人员编写数据库驱动的Web应用程序,而不需要从头开始编码。Django框架的开发者深知编写程序的痛点,所以,他们将尽可能地提供简单、易用且功能强大的功能模块。使用Django框架开发应用程序最大的优点是快速高效,它不需要使用者设计用户系统、搭建权限验证,也不需要构建缓存体系,甚至也不需要编写大量重复的代码去完成后台管理的功能等。使用Django框架从零搭建一个简单可运行的Web程序往往只需要几个小时。接下来看一看使用Django都需要做哪些准备工作吧。第2章 Django开发环境配置

正所谓“工欲善其事,必先利其器”,我们在真正编写应用之前,需要搭建基本的开发环境。对于将来要做的Django应用来说,由于它是完全基于Python的Web开发框架,所以,首先需要安装Python。为了让应用拥有独立的开发环境,还需要安装Python虚拟环境。之后,就可以安装本书的主角Django了。任何系统都需要数据存储,Django支持多种数据库,这里选择安装企业级开发中最流行的关系型数据库MySQL。最后,选择PyCharm这个IDE作为开发工具,它为Django等Python Web框架提供了非常好的支持。2.1 Python的安装与配置2.1.1 安装Python

在安装Python之前,首先需要确认Django支持的Python版本,之后,再去选择对应的版本安装。

本书将使用Django的2.0.7版本作为之后演示的版本,它所支持的Python版本是3.4、3.5、3.6、3.7。对于Python的各个版本,Django只支持最新的微版本(A.B.C)。提示

Django并不支持所有版本的Python,它需要根据Django环境选择安装对应的Python版本。关于不同的Django版本对Python的支持情况,可以查阅Django的官方文档。

这里,选用当前较新的Python版本3.7.0以支持Django的开发。不论是Windows、Linux还是macOS X,Python官方都提供了对应的安装程序。访问其官方网站即可下载对应操作系统的安装程序。

下载完成之后,双击安装包,运行安装程序。其安装过程与安装其他软件类似,唯一需要注意的地方是,对于Windows系统而言,Python的可执行文件默认是不会加入PATH变量中的,需要主动勾选“Add Python 3.X to PATH”。安装成功的界面如图2-1所示。图2-1 Python安装成功

安装完成之后,启动终端(Windows中使用命令提示符)输入python3回车,如果能看到类似下面的输出,就说明已经将Python成功安装到系统中了:2.1.2 Python包管理工具

Python社区提供了功能强大的第三方包,若想要使用这些包去扩展应用程序,就需要有包管理工具去下载和维护它们。

pip是目前比较流行的Python包管理工具,且它已经内置到Python 3.4及以上版本中了,所以,如果安装的是3.4及以上版本的Python,则pip已经安装在系统中了。

如果系统中没有pip或者版本比较低,则可以利用命令来安装或者将pip升级到最新的版本:

回车之后,会看到类似下面的输出:

这样,就完成了pip的安装或者更新。建议大家最好执行一下这个命令,即使系统中已经有pip了,这个命令也能把pip升级到最新的版本。

安装完pip之后,需要知道pip常用的几个基本命令。(1)安装package:pip install。(2)升级package:pip install–U。(3)卸载package:pip uninstall。(4)列出已经安装的package:pip list。2.2 虚拟环境的安装与配置

在做应用程序开发的时候不可避免地会遇到不同的应用程序依赖不同的包版本的情况。这样就有可能会出现依赖冲突的问题,特别是时间长了之后,这种情况会变得更加糟糕。举个简单的例子:假设之前开发的Django A应用依赖于Python 2.7,但是现在开发的Django B应用必须要使用Python 3.X版本,如果简单地将系统中的Python升级到3.X版本,就会导致A应用不可用,因为Python 2与Python 3中的部分语法是不兼容的。

为了解决这个问题,需要安装Virtualenv,利用它可以给每一个应用搭建虚拟且独立的Python运行环境。2.2.1 安装Virtualenv

安装虚拟环境比较简单,需要利用Python的包管理工具,执行命令:

安装过程中会看到类似下面的输出:

这样,就完成了虚拟环境的安装。2.2.2 创建应用运行的虚拟环境

安装完成Virtualenv之后,这里给将来的示例应用创建一个独立的Python运行环境,执行下面的命令:

执行过程中会看到类似下面的输出:

这样就创建了一个独立的Python运行环境。

对上述命令进行一些解释,具体如下。

virtualenv是刚刚安装的虚拟环境应用,利用这个命令就可以给其他的应用创建虚拟环境;-p参数是指定当前虚拟环境的Python解释器(如果不知道Python解释器所在的路径可以使用命令which python3查看),如果不指定,则会使用安装virtualenv时的解释器;最后的bbs_python37是虚拟环境的名称,这里需要注意的是,虚拟环境的名称最好是有意义的,当虚拟环境越来越多的时候,有意义的名称更加方便管理,例如这里的bbs代表的是应用名称,python37代表的是Python解释器的版本号。

新创建的Python环境会被放置到bbs_python37这个指定的目录下面,进入bbs_python37目录,执行命令启动虚拟环境:

执行之后会发现,命令提示符发生了变化,多了(bbs_python37)前缀,这就表明当前所处的是一个名为bbs_python37的Python运行环境。

退出虚拟环境,执行命令:提示

由于每一个虚拟环境都是独立存在的,它们之间互不依赖,所以,当不再需要某一个虚拟环境时,直接删除该虚拟环境的目录就可以

试读结束[说明:试读内容隐藏了图片]

下载完整电子书


相关推荐

最新文章


© 2020 txtepub下载