Django一个“高质量”小白的学习之路(给自己看)
第一天day1:
人类的思维倾向于直白、视觉和线性,还有好奇心,这是祖先遗传下来的思维习惯。
如果论结果,显然我是一个计算机学习的失败者。
因为我作为一个已经刚到不惑之年的中年男子,还在学习一些计算机"基础知识"(对标专业人士而言)。
我的思路是老一辈80后典型的思路,买来书,然后上机学习。
好,现在就从计算机书的生态开始。所谓有人的地方就有江湖。
一定要吐槽计算机书籍领域,也就是10-1开,就是你买10本计算机书,有1本是优秀的计算机书,会充分考虑你是一个初学者,或者即使考虑是专业者,也会按照正常的思维逻辑写。但是实际情况,90%以上的计算机作者写的书是只适合自己看的。
让我们用理工科思维进行分类一下:
- 计算机水平分类,高级,中级,低级 (这里的低级也指的是相对有一定技能的意思,并不是我这样的"小白"),分别对应A1,A2,A3
- 当老师的水平,写作的水平,高级,中级,低级,L1,L2,L3
- 已经写书和没有写书的人,分为Yes 和 No,Y和N
- 有责任心和没有责任心,分为Z1和Z0
那么社会上,很多是属于N-A1-L1,就是很多一流的高手很多,因为自己学的好,还能教的好,但是就是没有写书,这有很多因素造成的。因为这些高手基本上没有功夫出书,忙着事业呢或者压根不想分享技术,或者很多原因没有机会出书。但是不代表他们没有传承,好友间的分享,博客的写作,公司的技术分享会等等,只是我们普通人没有机会接触。
费曼物理学讲义一样的Y-A1-L1,就是一个绝佳例子,那就是为啥我碰到一本好书,我会感谢作者一辈子,我甚至想用我的所能打款给作者一点钱(中年男子有一点点经济基础)。
因为碰到技术问题,到百度上谷歌上搜索,总能遇到某某高手写了一篇非常浅显易懂的文章,瞬间有拍大腿的感觉。写的太妙了。于是大骂书中作者写这个知识点简直是"狗屎",浪费我的时间和精力。Y-A1-L1,很多一流的高手并且写书很好的人,很少。一句话,有责任心的作者适合当老师的作者Z1-Y-A1-L1≈0,凤毛麟角。
好了,我只想分享一些我自学的经验,还是说说我自己吧。
我是一个高质量的小白,来自网络什么高质量男性的梗,我给自己定位了"小白高质量",因为论学历,硕士研究生,论经济,小康,论时间自由,论学习力,
足够,我的问题在于,数学思维,太抠细节。然后通过计算机书籍看书学习,掉坑去了。因为不是学的纯计算机专业,很多基础知识很欠缺(我已经很谦虚了,哈哈)。当然我也不介意,有的人反向吐槽读者水平太弱,没有所谓的基础知识。是的,如果一个数学家看初中数学,当然无论写的多少晦涩难懂,都没关系。同样,一个计算机高手,看计算机书,都是看小学生加减一样简单,但是逆命题不成立啊。
但是从市场的角度来说,消费者我买了你的书,作者有义务写的精彩漂亮。但是由于技术类的书的特殊之处,因为是讲的是技术,所以哪怕作者抄袭官方文档,翻译一下,或者改一下,都是"政治正确"的,因为技术嘛,流水账的说明书,你没法吐槽作者,因为技术准确是第一位的。这里我忘记补充了另外一个维度,就是技术的准确性,很多书的作者写的东西是错误的。我买了一本小程序开发的书,作者直接巴拉官网的例子,改改占据三分之二的内容。这种毫无责任心的垃圾作者很多的。
写了这么多,我不想继续吐槽了,因为要为自己的年龄和时间负责。这种毫无意义的吐槽,类似这个社会道德滑坡,不是一个个体现象,是群体历史现象。
我买了《Django 2.0项目实战精例》,吃灰吃了几年,因为这是我豪横的习惯,书批量买,不看,哈哈。因为生活所迫嘛,要工作,要创业。
发现老外写的真特么循序渐进是本好书
后来发现出了第三版,我就去买了第三版
后来发现有了第四版本,是英文的,也下载来看了。
Django 2.0到Django3.0到4.0
下面开始我的学习笔记,我的受众群体是小白。
- 先安装python,我的版本是3.11.1
- 后安装django,我的版本是4.1.4
这个前提是安装了django,至于怎么安装,百度一下。用powershell看看
当然第二种方法是直接用一条命令
python -m django --version
创建第一个项目
博客
发现pycharm的一个好技巧
这样连带命令都不需要输入了
这样,
连注册app都帮你弄好了。pycharm 比较强大
我对照了Django 4 这本书为例,增加了一些新内容,比如一下这个,django的构架之生命周期,其实我一直对翻译过来的词汇表示难以理解
我又要吐槽现在的IT从业人员,翻译没有信达雅,再也出现不了类似基因,咖啡等翻译了。
request/response cycle request请求,response响应周期,所谓的life cycle 就是指的一个完整的数据流向周期或者完整的一个动作周期。
浏览器web brower发布请求,举个例子,网址就是最典型的请求,输入网址,就是让浏览器给远方的服务器发送命令。
然后django的url dispatcher 是url分发器,正确的定位到相应的view视图,view视图去到model里面搞,
搞完之后,就是database取数据,取完之后原路返回,到model 到 view 然后到模板templates,然后输出响应response到浏览器。
__init__.py,是空的,作用是告知python这是个憨憨,哦哦,不是憨憨,是整个文件夹是可以看做模块,module。可以理解为一坨。
asgi.py,正确的理解是你先查看cgi,然后回头发现这个是wsgi的升级版本,在django 3.0才加入,那个a字母就是异步的首字母
settings.py 项目的设置,没啥好说的,但是里面知识点不少
urls.py路由分发,没啥好说的,但是里面知识点不少(同上)
wsgi.py cgi的升级版
对于初学者来说,技术类的东西知识点太杂,而且具有强烈的步骤性,和模块性,编程技术是一方面,掌握编程之外的工具知识,部署知识等元知识也是非常重要的。
此时,我已经建立了项目名字叫mysite,同时建立了app名字为blog,由于我用的是pycharm配置一开始就设置了app,所以我
- 无须输入命令 python manage.py startapp blog
- 其次,setting里面已经帮我配置好了
至于'blog.apps.BlogConfig',和普通的blog有什么区别我找到了一个python的csdn博客,博主昵称叫大江狗,看样子是django发音的音译
姓尹,我称作尹老师吧,这个作者就属于A1-L1的,就是技术水平好,文章也写的很好
https://blog.csdn.net/weixin_42134789/article/details/108373452
参考https://docs.djangoproject.com/zh-hans/4.1/ref/applications/#django.apps.AppConfig
一句话结论,两种情况基本一样,用blog.apps.BlogConfig这个相对更好一点。
我摘录下尹老师的博文
Django的INSTALLED_APPS中应该写app名,还是AppConfig子类?
# settings.py 注册app
# 方式1:直接加入app名,
INSTALLED_APPS = [
'django.contrib.admin',
'app01',
]
# 方式2:直接加入app对应的AppConfig子类
INSTALLED_APPS = [
'django.contrib.admin',
'app01.apps.App01Config',
]
回答这个问题没有简易答案,一切还得从Django的AppConfig类说起。
配置信息和verbose_name - 你有的我也要
Django一个项目(project)由多个应用(app)组成,每个app的创建和注册体现了一个插拔的思想,即插即用。与project一样,每个app其实也有自己的配置信息,只是我们很少配置而已。项目的配置信息我们一般写在settings.py里,那么每个app对应的配置信息我们写在哪里? 答案是每个app目录下的apps.py里。与settings.py中以字符串形式配置相关信息不同,每个app的配置信息是通过继承Django的AppConfig类实现的。
在实际开发过程中,我们不需要编辑apps.py,给每个app手动添加配置信息,这是因为Django会根据app名生成默认的配置类。它继承了AppConfig类,里面只有name一个基本属性,如下所示:
但也有不少情况下我们需要给app添加额外配置信息。举个例子,我们在自定义模型(Models)时会给每个模型起个verbose_name(别名), 便于人阅读。同样的,我们也可以给app起个verbose_name, 这时我们就需要修改apps.py添加别名了。比如本例中app01这个名字可读性太差,我们最好给它起个别名,比如"用户管理",我们可以按如下修改代码:
或许你会问app的别名哪里会用到呢?Django的admin后台啊。一般app的创建名字都是英文,如果你希望以在admin中以中文显示app名,就必须用到app的verbose_name了。
那么还有什么情况下我们需要自定义app的配置信息呢?要回答这个问题,我们需要了解下AppConfig这个类的类的源码。。
AppConfig类 - 源码分析
Django的AppConfig类主要有如下属性和方法,部分源码见后面。属性里4个标红的属性可以自定义的,两个标红方法是可以重写的。
属性:
name:django应用的完整python路径,eg.'django.contrib.admin',在初始化参数中由app_name参数指定。
label:app的标签,这个名字必需独一无二,如果不设置即为app名。
verbose_name: app的别名,如果不设置即为app首字母大写形式。
path:django应用的文件系统的路径
module:django应用的根模块,是一个模块对象,eg.<module 'django.contrib.admin' from 'django/contrib/admin/__init__.py'>
apps:Apps注册表的引用,该注册表保存管理着这个AppConfig。当注册表注册这个AppConfig实例的时候,由注册表进行设置。
models_module:包含models的模块,也就是models.py文件,这是由import_models()设置,若没有则为None。
方法:
create方法:这是一个类方法,是一个工厂为INSTALLED_APPS的一个条目创建一个app config,返回是cls(app_name,app_module),即该类的一个实例。
ready方法: 子类可以覆盖此方法来执行初始化任务,例如注册信号和连接non-SQL数据库。
通过继承AppConfig类自定义label和自定义verbose_name一样简单,这里就不贴代码了。或许你会问在什么情况下需要自定义app的label呢?答案是:第三方库的app的名和你自己的app名可能存在命名冲突时,可以通过自定义label避开,因为app_label必须是独一无二的存在。
下面我们着重介绍下如何在继承AppConfig类时重写ready方法,这个在使用信号(signals)时会经常遇到的。
重写ready方法
假如我们有个account的app,包含了User和Pofile模型(1对1的关系),我们希望通过信号实现创建一个新User实例的同时也创建一个Profile实例。这时我们可以在account文件夹下新建signals.py,需要修改account文件下apps.py,重写ready方法,确保Django项目初始化时即可导入创建的信号监听函数。
# account/signals.py
第一天day2:
运行项目之前,先migrate
这个migrate命令简单,但是需要了解很多关于数据库的知识点,《django 4.0 by example》的作者在这一章没有细讲
那只好我自己解释了:
在migrate之前有一个makemigrations,看上去是名词,但是名词里面有个make是动词,migrations是名词
题外话:怎么理解老外的造词呢,之前的verbose name我也特意百度了下verbose
你说放到计算机里面怎么理解?只能按照它最终的行为结果来理解成汉语对应的"别名",所以
我们中国人,见此就条件反射为"别名",verbose好像就是罗里吧嗦的解释,等价于别名
还有一个slug,天哪第一次看到,对于我这个高级小白,理解不了什么是slug,查英文
从这里也没办法引申,难道鼻涕虫是有粘着的作用?引申为一行?进而引申为处理后的标题?
言归正传,makemigrations是自定义数据库model之后的生成sql原生语句的准备工作
- 先makemigrations
- 再migrate
- 但是系统自带的应用,连makemigrations都不需要,因为已经放到虚拟环境lib里面了
我用Everything大法看一下
接下去讲解setting.py 用pycharm的Debug,太好用了,解答了我的困惑,书上都是说说的,没有实际看到
所以BASE_DIR到底是什么,做个实验就发现了
可见BASE_DIR就是E:\mysite
项目根目录哦!!
纸上得来终觉浅,绝知此事要躬行
虽然是个小细节,人类天生就是好奇心很重,寻根究底是本能。
这个secret_key据说是为了项目安全考虑,这里我也不知道,但是查资料麻烦。
先做个标记
DEBUG开起来就是说明调试环境,知识点:真实环境中要关闭
开启Debug,这个ALLOWED_HOSTS = []为空
但是设置Debug=false,关闭的时候,就是等于生产环境了,生产环境这个词汇也是翻译过来的
product真的是生产的意思吗?所以不如翻译成真实服务器环境。
生产环境=真实服务器环境,所以为啥小白不理解计算机术语了,隔行如隔山,但是很多人
是不希望你入行的。
回到Debug=false,ALLOWED_HOSTS = 就是需要等于你主机ip了
接下去INSTALLED_APPS,是六个自带app
• django.contrib.admin: An administration site 后台管理页面
• django.contrib.auth: An authentication framework 认证框架
• django.contrib.contenttypes: A framework for handling content types处理内容类型的框架
• django.contrib.sessions: A session framework 处理session的框架
• django.contrib.messages: A messaging framework处理消息的框架
• django.contrib.staticfiles: A framework for managing static files处理静态文件的框架
接下去就是MIDDLEWARE 中间件,这个翻译也是不理解的,中间件,就是中间的软件
其中英文的ware就是软件的意思。我理解为不是一个完整的框架,是可以四处使用的软件api
接口,或者是理解成反复调用的类或者代码函数模块,一样的道理,否者为啥不弄成框架?
为啥不在上面INSTALLED_APPS呢,应该够不到这个级别,代码量应该少一点。这个只是我推测
等我熟悉框架去查看源码再来回过头来验证。
接下去是ROOT_URLCONF = 'mysite.urls' 这里就是和那个admin的url原理差不多,这里是指根路由,所谓的根就是BASE_DIR
现在来理解一下templates
BACKEND,有两种,一种是DTL这个D就是django就是自带的模板,一个是j开头的模板
配置就是改这一行
DIRS,这里就理解了'DIRS': [BASE_DIR / 'templates'] 这里的BASE_DIR就是E:\mysite所谓的根目录下的自带的templates文件夹
APP_DIRS true就是默认到app里面去找模板
接下去是数据库,数据库很好理解,但是知识点也很多。这里不赘述
AUTH_PASSWORD_VALIDATORS 密码验证相关,在此时我并不了解,等后期深入再来理解这个含义
接下去就是顾名思义,国际化=本地化
Internationalization
静态资料,和是否自定义主键字段
# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/4.1/howto/static-files/
STATIC_URL = 'static/'
# Default primary key field type
# https://docs.djangoproject.com/en/4.1/ref/settings/#default-auto-field
DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'
这个STATIC_URL = 'static/'也有重要的知识点,到时候做笔记
到此为止,setting的第一轮理解到此结束,书上贴心的说了一句
Don't worry if you don't understand much about what you're seeing here. You will learn more about
the different Django settings in the following chapters.
一句Don't worry让我掉眼泪。
再看国内的书,一坨屎,就是堆砌知识点,还不炫技,就是本着怎么样让读者看不懂怎么来。
project与app的关系图
一个项目里面有很多app,但是一个app只有一个项目,项目把不同的app抽象出来进行管理,这样就是一种数学上的因子提取模型
虽然说数学的实际用处不大,但是背后的逻辑类比,人类的隐喻思维模式是一致的。
由于进行共同管理,就会有共同管理的问题,这就是为啥设置了setting,每一个独立的app还有apps.py这种管理自己的配置文件
这是一种哲学
__init__.py,告诉python这个文件夹是一个Module
admin.py 要不要注册到管理后台的一个文件,要注册到后台,这个是可选的,就是要不要可视化的来管理应用的数据模型
apps.py 是和setting一样的,只不过这个是管理自己的,所以取名apps.py
models.py 所有数据库表在这里设计
tests.py 我知道是用来测试的,但是我还没有学到不知道怎么用
views.py 视图,不过这样翻译理解不了,大白话的意思就是view用来链接model,操控你request后的数据,reponse到模板中
在处理请求request中实际就是和model数据库进行交互,交互完了把结果response(就是带有返回值的)发射到html模板里面
拼凑成为浏览器最终的展示页面,因为每一个页面实际上有固定的数据+动态的数据的html组成,就是加载各种html元素,组成一张完整的html拼图,最后到浏览器中显示。
好比数学中,你先学会最小模型,然后其他的概念很好理解。
所以views.py+templates配合就是读取数据并且整合输出到浏览器的一系列操作。views纯python代码
templates是符合python改装过的简单循环,链接等语句,但是不涉及到数据库操作等敏感内容,原因是官方文档说了
责任要明确,templates有可能不是程序员负责的,是前端人员负责。那前端人员有可能不懂python代码
就在此时我的思维联系到了,面向对象和数据库的关系,然后百度了一下,果然有高手很好的文章分享了
https://www.cnblogs.com/Nathan2008/archive/2007/11/03/947815.html
还是2007年的。
互联网的价值体现
面向对象就是内存数据库,可以这么理解
比如JSON在JavaScript里面就是轻量级的不需要数据库的数据库
数据是代码的灵魂,所来说去代码是自动化操控数据,产生数据,运行数据的一串指令。
至于存储数据,永久保存,离线存储,就得靠数据库了。
建立第一个发布文章的model
# Create your models here.
class Post(models.Model):
title = models.CharField(max_length=250)
slug = models.SlugField(max_length=250)
body = models.TextField()
def __str__(self):
return self.title
title代表每一篇文章都有的标题
slug就是链接美化器
body文章内容
什么charfiled,slugfiled,textfield 都是不同存储数据类型而已
上面系统自动帮我们创建了一个主键,主键的默认设置在setting里面
发布时间,创建时间,修改时间的字段
• publish: This is a DateTimeField field that translates into a DATETIME column in the SQL database.
We will use it to store the date and time when the post was published. We use Django's
timezone.now method as the default value for the field. Note that we imported the timezone
module to use this method. timezone.now returns the current datetime in a timezone-aware
format. You can think of it as a timezone-aware version of the standard Python datetime.now
method.
• created: This is a DateTimeField field. We will use it to store the date and time when the post
was created. By using auto_now_add, the date will be saved automatically when creating an
object.
• updated: This is a DateTimeField field. We will use it to store the last date and time when the
post was updated. By using auto_now, the date will be updated automatically when saving
an object.
定义一个顺序
Defining a default sort order
这里的model封装了数据库sql语句,可以把建立字段,以及各种元信息展示都在这里完成
所以meta,就是元
在admin.py中注册一下
这样就能可视化的管理数据库模型Post
如图
人工添加一篇文章
retrieve data 获取数据的意思