【051】Python全栈日记-Django(五)

版权声明:作者:人学物理死的早 出处:https://blog.csdn.net/weixin_39561473 本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接。 https://blog.csdn.net/weixin_39561473/article/details/86582855

今天重要的任务就是优化之前做的学生统计登陆注册项目,并学习多表联查获取数据库信息。

 

一、模板系统                                                                           

观察之前做的学生列表页和学生详情页还有首页,你会发现,图中红圈框出来的地方是完全一致的:

那每个网页都是这些代码,看着非常繁琐,那有没有一种方法,只需要写在一个网页中,其他网页就都有了呢?

 

模板系统应运而生:

 

1、模板系统第一步:找出个性,提取共性。

扫描二维码关注公众号,回复: 5040221 查看本文章

观察首页,学生列表和学生详情页:可以发现每页的个性都集中在<div class="container-fluid"></div>标签块中。

 

2、新建一个html文件,命名为base.html,将代码全部复制过去,删除<div class="container-fluid"></div>块所有内容。

那如何将其他页面的内容填充在这个共性模板中呢?

通过{% block 块名 %} {% endblock %}标签来定位个性的代码放在何处

 

3、修改个性页

首先删除共性的内容,只留下<div class="container-fluid"></div>块所有内容。

那如何把共性的内容导入呢?

通过继承标签{% extend ‘模板html’ %},来导入base.html中的内容

通过定位把个性内容,定位到当初在模板文件中定位标签处。

用这个方法,修改其他页面,简化页面代码。

 

 

 

二、urls子路由系统

Django鼓励大家进行独立的松耦合开发。

之前将所有的路由都放到了主urls当中,如果项目做的非常大,那url里面东西会非常多,所以django支持我们自己编写子url。

 

在app当中创建urls.py文件

 

在子urls文件中写的是关于app的路由,例如在这个项目里,学生列表和学生详情就是在app中定义的主要部分所以应该放在app的子路由中。而登陆注册是一个公共的逻辑应该放在主urls中。

子路由:

因为在访问的时候,永远访问的是主路由,所以要在主路由中引导至子路由,通过include方法,实现主路由包含子路由,如下图:访问student/就是相当于访问子路由。

这里有个小技巧,通常访问主页的时候,都是直接输入网址进行访问,并不会输入index/,所以添加一条路由,使用正则,如果匹配为空,跳转至主页re_path(‘^$’,index)。

 

 

 

路由分离之后效果如下,由于访问子路由是通过主路由的student/再到子路由,所以一定要修改网页点击跳转的地址。

 

 

 

还有一种urls的改法,列表有个属性,通过加号可以进行列表的拼接

url也是列表,所以可以使用这种方法对url进行划分,但是不推荐使用。

 

 

 

三、Url命名组

命名组可以使用命名的正则表达式组来捕获 URL 中的值并以关键字参数的方式传递给视图函数。

 

在 Python 正则表达式中,命名正则表达式组的语法是 (?P<name>pattern),其中 name 是组的名称,pattern 是要匹配的模式。

 

Name必须和传入视图函数的函数形参保持一致,要不无法传入。

一个参数并看不出来有什么特别,加入网址传入的是一段日期假如:127.0.0.1/2019-01-09

可是视图中的函数需要的是年月日三个参数,那就只能使用正则的方法设为三个参数。

Path(‘shili/(?P<y>(\d+){4})\-(?P<m>(\d+){2})\-(?P<d>(\d+){2})’)

 

Url传参还有一种不需要正则的方法:

在函数后面再加一项字典,字典中存储的就是参数,{‘page’:1},而且Url字典传参优先级大于正则匹配传参。

在之前的学生列表页,即使第一页,也会在url中显示1,作为列表首页应该是直接通过http://127.0.0.1:8000/student/studentlist/访问到的而不是http://127.0.0.1:8000/student/studentlist/1/,这时就可以通过字典传参,当不写1的时候传个参数为{‘page’:1}

还可以通过这个方法进行数据库的传递,把数据库赋值给变量studentObj,然后传入到函数中,这样只获取一次数据库数据,就可以进行多次使用,减少了数据库的压力

 

 

 

四、Url反向代理

当我们具有多个app,每个app中又有多个index页面,url就会变得太过复杂,有重复的时候,我们可以使用name进行反向代理

以前href = ‘/index/‘,加了反向代理后,就可以写为href = ‘{% url ‘index’ %}’。

 

 

 

五、APP内部的静态文件

除了url和app需要独立,静态文件也是需要独立,Html和静态文件的独立形式是不一样的。

 

这里要明白app是干啥呢,app是一个独立的模块,里面的所有静态文件都是已经写好了,我们可以直接把app放在任何的项目中使用,所以其中的静态文件都是写死的。不会因为换了项目就找不到静态文件。

 

1、新建一个项目来练习独立app,创建2个app,然后在setting安装好app

 

2、独立HTML

在每个app下创建templates文件夹,名字一定是templates,因为在配置文件中,会自动识别名字为templates的文件夹

然后在templates中构建静态文件结构,为了区分每个app的templates,加上区分目录,在区分目录中创建index.html

写在视图中的返回值地址就需要加上区分文件

 

3、独立静态文件

在线上和项目当中,django使用不是一套静态文件,app中的静态文件为仅供app使用的写死的静态文件,例如固定的样式,固定的图片。而上传的图片,每个人的头像,这些不应该写死在页面上的的静态文件,还是存在在项目的静态文件夹中。

 

 

但是当我们的项目部署在Apache和Nginx当中的时候,他们是读取不到app内的static文件的,这时候需要在配置文件中设置静态根目录:

配置静态根目录

然后通过命令收集静态文件到我们配置的根目录下,这样Apache和Nginx就能获取到所有的静态资源包括app内:

在虚拟环境下的项目文件根目录执行命令

(djangoProject) E:\pythonProject\项目文件名>python manage.py collectstatic

收集到120个静态文件:

再去看根目录的静态文件就会发现,其实120个都是admin自带的,剩下两个是我们写的。

 

当然在正常编写中,为了更好的完成项目,还是使用之前的STATICFILES_DIRS = 的形式,只有在部署时改为STATIC_ROOT

 

4、在html中加载静态资源

在页面开头添加{% load static %},会加载整个项目的所有静态资源,然后通过{% static xxx %}来使用。

[1]加载app中的固定资源,直接使用从路径区分文件往下写:

[2]加载主static的非固定资源,例如库中的图片等:

首先配置MEDIA,在配置文件中添加代码:

MEDIA_URL 媒体文件的前端路由

MEDIA_ROOT 媒体文件的路径

例如我们要通过for遍历出来从视图传过来的用户信息,获取每个用户的图片:

{% static 变量.photo.url %}

 

 

 

 

 

六、Django模型关系字段介绍与使用

回到之前的项目,最开始我们还有一个老师表,我们再创建一个专业表(python,java,ui,web),加上一直使用的学生表,有如下关系:

 

[1]学生 和 专业 关系

一个学生对应一个专业

一个专业对应多个学生

一对多关系使用的是mysql中的 Foreignkey 外键

 

所以有两种查询:

查询这个学生对应的专业

查询这个专业所有学生

 

[2]学生 和 老师的关系

一个学生对应多个老师

一个老师对应多个学生

所以一定会有一个中间表做学生老师关联

多对多关系有一个字段为:ManyToManyField

 

所以也有两种查询:

查询一个老师教过的所有学员

查询一个学员所有的老师

 

1、重建数据模型,删除库中学生表、老师表,然后重新同步数据,创建表

[1]重建数据模型

学生数据需要修改两个字段,

 

第一是科目(Project)字段,因为学生对于科目是一个一对多的字段,所以使用内置字段ForeignKey(Project,on_delete=True),Project是上面的科目表,把学生和科目关联起来,手动添加SQL数据库中的ON_DELETE=True字段进行约束,防止你的数据库后端强制引用完整性,这将导致 IntegrityError 错误。

 

第二是老师字段,学生和老师是多对多的,所以使用ManyToManyFiled字段,并绑定Teacher表:ManyToManyFiled(Teacher)

 

还有一点更要注意,学生表需要放在teacher和peojct表下,因为student关联了这两个表。

 

[2] 删除库中学生表、老师表

可以使用pycharm自带的数据库进行删除

[3]同步数据库

进入虚拟环境再进入项目文件夹下:

Python manage.py check 检查错误

Python manage.py makemigrations 创建表

Python manage.py check migrate 同步字段

Python manage.py createsuperuser 创建admin管理台账户

 

这样表就建好了:

而且你会发现django会自动帮你创建关系表。

 

[4]配置admin文件,通过admin写入数据:(user是之前的注册账户)

运行项目,登陆管理台添加账户:

创建几个科目、老师和学生后,查看数据库:学生表中并不会显示老师数据。

 

 

2、数据查询

表建好了,接下来就是数据查询了:

创建一个html页面,写好视图和路由,来查看数据查询的效果

 

[1]一对多获取:一个学科的所有学生

首先获取一个学科:p = Project.objects.get(id = 1)

然后获取学科对应的学生:p_s = p.student_set.all()

xxx_set是系统提供的方法,xxx为取的表的名字的小写,_set是规定好的方法固定格式,拼接起来形成完整方法,all是获取所有数据。

 

[2]多对多获取数据

一个老师对应的所有学生:

先取一个老师:t = Teacher.object.get(id = 1)

然后获取该老师的所有学生:t_s = t.student_set.all()

 

一个学生对应的所有老师

先获取一个学生:s = student.object.get(id = 1)

然后获取该学生的所有老师:s_t = s.teacher.all()

因为学生有老师这个字段,所以可以直接通过teacher来获取不需要set方法。

 

(因我在我设置表的时候,学生表用的小写,老师和科目首字母用的大写,所有获取时大小写有区别)

将参数传入查询.html这个页面,在该页面获取数据:

一对多关系 可以直接通过学生获取到科目然后获取到科目表中的科目名称字段和描述字段

 

 

猜你喜欢

转载自blog.csdn.net/weixin_39561473/article/details/86582855
今日推荐