Django blog项目知识点总结
数据库操作部分
当我们在Django项目中的models.py下写好创建表的代码后。为了创建好这些数据库表,我们再一次请出我的工程管理助手 manage.py。激活虚拟环境,切换到 manage.py 文件所在的目录下,分别运行 python manage.py makemigrations
和 python manage.py migrate
命令:
F:\myblog>python manage.py makemigrations
Migrations for 'blog':
blog\migrations\0001_initial.py
- Create model Category
- Create model Post
- Create model Tag
- Add field tags to post F:\myblog>python manage.py migrate
Operations to perform:
Apply all migrations: admin, auth, blog, contenttypes, sessions
Running migrations:
Applying contenttypes.0001_initial... OK
Applying auth.0001_initial... OK
Applying admin.0001_initial... OK
Applying admin.0002_logentry_remove_auto_add... OK
Applying contenttypes.0002_remove_content_type_name... OK
Applying auth.0002_alter_permission_name_max_length... OK
Applying auth.0003_alter_user_email_max_length... OK
Applying auth.0004_alter_user_username_opts... OK
Applying auth.0005_alter_user_last_login_null... OK
Applying auth.0006_require_contenttypes_0002... OK
Applying auth.0007_alter_validators_add_error_messages... OK
Applying auth.0008_alter_user_username_max_length... OK
Applying blog.0001_initial... OK
Applying sessions.0001_initial... OK
然后我们可以具体查看终端里Django究竟是做了什么为我们创建数据表的?实际是通过ORM将Python命令翻译为SQL语言,操作数据库。
F:\myblog>python manage.py sqlmigrate blog 0001
BEGIN;
--
-- Create model Category
--
CREATE TABLE `blog_category` (`id` integer AUTO_INCREMENT NOT NULL PRIMARY KEY, `name` varchar(100) NOT NULL);
--
-- Create model Post
--
CREATE TABLE `blog_post` (`id` integer AUTO_INCREMENT NOT NULL PRIMARY KEY, `title` varchar(70) NOT NULL, `body` longtext NOT NULL, `created_time` datetime(6) NOT NULL, `modified_time` datetime(6) NOT NULL, `
excerpt` varchar(200) NOT NULL, `author_id` integer NOT NULL, `category_id` integer NOT NULL);
--
-- Create model Tag
--
CREATE TABLE `blog_tag` (`id` integer AUTO_INCREMENT NOT NULL PRIMARY KEY, `name` varchar(100) NOT NULL);
--
-- Add field tags to post
--
CREATE TABLE `blog_post_tags` (`id` integer AUTO_INCREMENT NOT NULL PRIMARY KEY, `post_id` integer NOT NULL, `tag_id` integer NOT NULL);
ALTER TABLE `blog_post` ADD CONSTRAINT `blog_post_author_id_dd7a8485_fk_auth_user_id` FOREIGN KEY (`author_id`) REFERENCES `auth_user` (`id`);
ALTER TABLE `blog_post` ADD CONSTRAINT `blog_post_category_id_c326dbf8_fk_blog_category_id` FOREIGN KEY (`category_id`) REFERENCES `blog_category` (`id`);
ALTER TABLE `blog_post_tags` ADD CONSTRAINT `blog_post_tags_post_id_a1c71c8a_fk_blog_post_id` FORE
ALTER TABLE `blog_post_tags` ADD CONSTRAINT `blog_post_tags_tag_id_0875c551_fk_blog_tag_id` FOREIG
ALTER TABLE `blog_post_tags` ADD CONSTRAINT `blog_post_tags_post_id_tag_id_4925ec37_uniq` UNIQUE (
COMMIT;
查看这些SQL命令可以帮助我们理解Django的ORM运行机制。
在 manage.py 所在目录下运行 python manage.py shell
命令:
(blogproject_env) C:\Users\yangxg\Workspace\blogproject>python manage.py shell
Python 3.5.2 (v3.5.2:4def2a2901a5, Jun 25 2016, 22:18:55) [MSC v.1900 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
(InteractiveConsole)
>>>
这就打开了交互命令行。我们可以在其中具体添加数据表的信息。
>>> from blog.models import Category, Tag, Post
>>> c = Category(name='category test')
>>> c.save()
>>> t = Tag(name='tag test')
>>> t.save()
比如在这里实例化了一个 Category
类和一个 Tag
类,为他们的属性 name
赋了值。为了让 Django 把这些数据保存进数据库,调用实例的 save
方法即可。
博客首页
Django处理HTTP请求
后台与前端交互,请求响应流程是怎么实现的?
基本流程就是用户请求,浏览器发送HTTP请求,服务端接收然后返回一个响应(过程包含了三次握手,四次挥手),浏览器读取数据并显示。
在Django中,如何处理请求的呢?内部流程实现是,首先绑定URL和views函数,其次是编写views函数处理请求,配置项目URL映射,分配路由,最后返回数据给前端渲染模板显示内容。在views.py文件函数中,为了显示引用的models中的字段内容,需要调用__str__方法。
调用from django.utils.six import python_2_unicode_compatible,然后进行可视化处理,在自定义函数上添加装饰器@python_2_unicode_compatible.
前端如何引入静态文件配置JS样式呢?
需在首页index.html中正确配置路径,引入js样式。在html文件顶部声明静态文件部署:{% load staticfiles %}
在前端使用Django自带的模板语言渲染数据,关键要区分模板变量和模板标签两类。模板变量语法为{{ xxx }},中间嵌套着要渲染的变量内容,可以包含变量和条件判断语句。模板标签语法为{% xxxss %} ,中间为需渲染的内容。
该博客项目直接复用了网上的一个网页模板,关键运用时可以微调布局。这块是最考验前端功底的部分了,如何调整的样式优美又不杂乱?如何才可显示最少信息又不失要素。达到良好的用户交互体验。
基于类的通用视图:ListView 和 DetailView
在web开发中,有些视图函数虽然处理对象不同,但是基本的逻辑是一致的。比如说一个博客和一个论坛,虽然表现方式不同,但本质上首页都是展示的一系列有序的文章/帖子列表。就首页视图函数来说,处理逻辑都是从数据库中取到最近的文章列表,然后按照时间顺序传给前端,前端渲染并显示。
Django中将实现这一系列逻辑的代码提炼出来,成为一系列的通用视图函数,即基于类的通用视图(Class Based View)。这是有别于基于函数的通用视图的工具箱。
那么如何来利用类视图减少开发时间,提升开发效率呢?
这里要涉及到Django内建基类视图API中的通用显示视图函数,包含两个子函数ListView 和 DetailView。官方文档是如此总结这两个函数的:
The two following generic class-based views are designed to display data. On many projects they are typically the most commonly used views.
#两个通用基类视图函数被用来显示数据。他们越来越广泛的被运用在许多项目中。
ListView
比如一个博客项目中,有几个不同的views函数都是利用的数据库中文章列表数据,只是所选取的数据略有不同,针对这种情况,可以用ListView函数。
要写一个类视图,首先要继承Django提供的某个类视图,具体继承哪个,需要看视图功能决定。
比如 我们可以编写一个IndexView类函数,它
的功能是从数据库中获取文章(Post)列表,ListView
就是从数据库中获取某个模型列表数据的。
当然,我们实现将基于函数的views更改为类视图,之后要将url中的路由映射也更改下,不过这里是将类视图改为函数视图了,是不是有点绕?
不过记住这个功能的实现方法就好了,直接调用Django提供的as_view()方法就可以了。
app_name = 'blog'
urlpatterns = [
url(r'^$', views.index, name='index'),
...
] 更改为 app_name = 'blog'
urlpatterns = [
url(r'^$', views.IndexView.as_view(), name='index'),
... ]
对于要获文章列表中某一分类下的文章,我们需要从URL中捕获的文章ID并从数据库中获取分类,然后使用filter过滤器获取该分类下全部文章。
举例来说,这种情况下代码可以这么修改:
blog/views.py class CategoryView(ListView):
model = Post
template_name = 'blog/index.html'
context_object_name = 'post_list' def get_queryset(self):
cate = get_object_or_404(Category, pk=self.kwargs.get('pk'))
return super(CategoryView, self).get_queryset().filter(category=cate)
在父类中,get_queryset()方法默认取到所有的文章列表,我们只是想要分类中的一部分,所以覆写了get_queryset()方法。
这里首先根据从URL中捕获的数据获取id来分类数据,在类视图中,从 URL 捕获的命名组参数值保存在实例的 kwargs
属性(是一个字典)里,非命名组参数值保存在实例的 args
属性(是一个列表)里。所以这里使用了 self.kwargs.get('pk')
来获取从 URL 捕获的分类 id 值。然后我们调用父类的 get_queryset
方法获得全部文章列表,紧接着就对返回的结果调用了 filter
方法来筛选该分类下的全部文章并返回。
DetailView
我们经常会有这种需求,从数据库中取出一条数据,比如说文章详情,我们需要获取到对应数据并返回前端模板渲染。对于这种需求,Django提供了DetailView类视图函数解决。
该类视图函数继承链为
class django.views.generic.detail.DetailView
While this view is executing,self.object
will contain the object that the view is operating upon.# 当该视图执行时,self.object包含所有在视图
上操作的对象。可理解为获取到的对象容器
Ancestors (MRO)
该视图函数继承的属性和方法来自于这些视图函数:
This view inherits methods and attributes from the following views: django.views.generic.detail.SingleObjectTemplateResponseMixin
django.views.generic.base.TemplateResponseMixin
django.views.generic.detail.BaseDetailView
django.views.generic.detail.SingleObjectMixin
django.views.generic.base.View
官方给出的例子中:
from django.views.generic.detail import DetailView
from django.utils import timezone from articles.models import Article class ArticleDetailView(DetailView): model = Article def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['now'] = timezone.now()
return context
这里仍然与ListView一致,从 URL 捕获的命名组参数值保存在实例的 kwargs
属性(是一个字典)里,非命名组参数值保存在实例的 args
属性(是一个列表)里。所以这里使用了 get_conext_data(**kwargs)
来获取从 URL 捕获的上下文数据。
分页功能
分页功能由 Django 内置的 Paginator
类提供。这个类位于 django/core/paginator.py,需要使用它时,只需在适当的地方导入这个类即可。
只需实例化一个 Paginator
对象,并在实例化时传入一个需要分页的列表对象,就可以得到分页后的对象数据。注意,分页对象是列表类型数据。
用paginator给文章列表分页。
在基于类的视图ListView中,分类逻辑已经含括在内了,我们只需要指定paginate_by属性开启分页功能。
ListView类视图中,包含了有关分页的几种方法,要记住:
paginator
,即Paginator
的实例。page_obj
,当前请求页面分页对象。is_paginated
,是否已分页。只有当分页后页面超过两页时才算已分页。object_list
,请求页面的对象列表,和post_list
等价。所以在模板中循环文章列表时可以选post_list
,也可以选object_list
。
分页功能拓展
想要分页显示这种效果
先来分析一下导航条的组成部分,可以看到整个分页导航条其实可以分成 七个部分:
- 第 1 页页码,这一页需要始终显示。
- 第 1 页页码后面的省略号部分。但要注意如果第 1 页的页码号后面紧跟着页码号 2,那么省略号就不应该显示。
- 当前页码的左边部分,比如这里的 3-6。
- 当前页码,比如这里的 7。
- 当前页码的右边部分,比如这里的 8-11。
- 最后一页页码前面的省略号部分。但要注意如果最后一页的页码号前面跟着的页码号是连续的,那么省略号就不应该显示。
- 最后一页的页码号。
回顾一下显示分页的步骤,经典的 Django 三部曲。首先是定义视图函数,然后编写模板文件,最后将视图函数和 URL 模式绑定。
RSS订阅实现
博客中的rss
RSS(Really Simple Syndication 简易信息聚合)是一种描述和同步网站内容的格式,它采用 XML 作为内容传递的格式。简单来说就是网站可以把内容包装成符合 RSS 标准的 XML 格式文档。一旦网站内容符合一个统一的规范,那么人们就可以开发一种读取这种规范化的 XML 文档的工具来聚合各大网站的内容。例如一个读者可能关注了很多的博客网站,如果这些博客网站都支持 RSS 订阅的话,他就只需要一个聚合阅读器订阅这些博客,就可以在聚合器工具里看到全部博客的更新内容,而不必再分别访问各个博客去看有没有内容更新了。
在django中内置了根据网站的内容生成规范化的 XML 文档的方法,接下来我们是用这个方法来实现RSS订阅文档。
比如用如下blog项目应用目录下建立一个create.py
blog/create.py from django.contrib.syndication.views import Feed from .models import Post class AllPostsRsscreate(Feed):
# 显示在聚合阅读器上的标题
title = "Django 博客" # 通过聚合阅读器跳转到网站的地址
link = "/" # 显示在聚合阅读器上的描述信息
description = "Django 博客" # 需要显示的内容条目
def items(self):
return Post.objects.all() # 聚合器中显示的内容条目的标题
def item_title(self, item):
return '[%s] %s' % (item.category, item.title) # 聚合器中显示的内容条目的描述
def item_description(self, item):
return item.body
该段代码是要指定生成XML文档,逻辑依然是获取对象列表,然后提取所需数据('[%s] %s' % (item.category, item.title)),接下来在模板中渲染显示。
这里视图改完了,继续在URL和前端模板中渲染即可。
简单的全文搜索
首先要提,全文搜索的对象是什么?数据库中存储的信息。那么数据库信息查询要用到的底层技术是什么?必然是算法了,数据各种索引的出现都是为了加速查询而创建的种种算法,优化数据的存储结构。
在前端表单中,我们需要用到表单的 action
属性的值为 {% url 'blog:search' %}(虽然我们还没有写这个视图函数),表明用户提交的结果将被发送给 blog 应用下 search 视图函数对应的 URL。
Django blog项目知识点总结的更多相关文章
- blog项目知识点梳理
1.获取图片验证码: def get_validCode_img(request): # 方式1: # import os # path= os.path.join(settings.BASE_DIR ...
- Django ---- blog项目学习所得
一.登录功能 1.采用ajax 提交form表单的方式 2.后台生成随机验证码,登录时提交验证码 3.用PLI库生成随机验证码,置于session中,登录时与前台提交的code进行upeer()的验证 ...
- Django学习笔记(19)——BBS+Blog项目开发(3)细节知识点补充
本文将BBS+Blog项目开发中所需要的细节知识点进行补充,其中内容包括KindEditor编辑器的使用,BeautifulSoup 模块及其防XSS攻击,Django中admin管理工具的使用,me ...
- BBS+Blog项目流程及补充知识点
项目流程: 1. 产品需求 (1)基于用户认证组件和Ajax实现登陆验证(图片验证码) (2)基于forms组件和Ajax实现注册功能 (3)设计系统首页(文章列表渲染) (4)设计个人站点页面 (5 ...
- Django快速学习搭建blog项目
新手学习Django,本文学习的文档是<Django Web开发指南>.好了我也是新手,没什么好说了,go!- 首先先确定环境,我是在linux(Ubuntu14.04 gnome)下. ...
- Django学习笔记(20)——BBS+Blog项目开发(4)Django如何使用Bootstrap
本文学习如何通过Django使用Bootstrap.其实在之前好几个Django项目中已经尝试使用过了Bootstrap,而且都留有学习记录,我已经大概有了一个大的框架,那么本文就从头再走一遍流程,其 ...
- Django学习笔记(18)——BBS+Blog项目开发(2)主体思路及流程
这篇博客主要完成一个BBS+Blog项目,那么主要是模仿博客园的博客思路,使用Django框架进行练习. 准备:项目需求分析 在做一个项目的时候,我们首先做的就是谈清楚项目需求,功能需求,然后才开始写 ...
- Django学习笔记(17)——BBS+Blog项目开发(1)验证码功能的实现
本文主要学习验证码功能的实现,为了项目BBS+Blog项目打下基础. 为了防止机器人频繁登陆网站或者破坏分子恶意登陆,很多用户登录和注册系统都提供了图形验证码功能. 验证码(CAPTCHA)是“Com ...
- BBS项目知识点汇总
目录 bbs项目知识点汇总 一. JavaScript 1 替换头像 2 form表单拿数据 3 form组件error信息渲染 4 添加html代码 5 聚焦操作 二 . html在线编辑器 三 . ...
随机推荐
- mongodb给我们提供了fsync+lock机制把数据暴力的刷到硬盘上
能不能把数据暴力的刷到硬盘上,当然是可以的,mongodb给我们提供了fsync+lock机制就能满足我们提的需求. fsync+lock首先会把缓冲区数据暴力刷入硬盘,然后给数据库一个写入锁,其他实 ...
- BZOJ_4154_[Ipsc2015]Generating Synergy_KDTree
BZOJ_4154_[Ipsc2015]Generating Synergy_KDTree Description 给定一棵以1为根的有根树,初始所有节点颜色为1,每次将距离节点a不超过l的a的子节点 ...
- 基于WinDbg的内存泄漏分析
在前面C++中基于Crt的内存泄漏检测一文中提到的方法已经可以解决我们的大部分内存泄露问题了,但是该方法是有前提的,那就是一定要有源代码,而且还只能是Debug版本调试模式下.实际上很多时候我们的程序 ...
- ftp主要流程
判断是否是root用户,若不是则提示并退出. 建立server socket. 等待用户连接,并建立相应用户的子进程.
- bzoj4144
最短路+最小生成树 有点忘了... 这题只要判断能不能就行了 具体做法是把所有加油站放到堆里然后跑dij,然后把边权w=d[u]+d[v]+w,跑最小生成树 对于点对(x,y)是否能到达只要判断最大瓶 ...
- CF-805C
C. Find Amir time limit per test 1 second memory limit per test 256 megabytes input standard input o ...
- mysql分页性能
- select * from userinfo limit 20000,10 # 数据越往后越慢 - 索引表中扫: select * from userinfo where id in (sele ...
- mysql 、redis的区别
我们知道,mysql是持久化存储,存放在磁盘里面,检索的话,会涉及到一定的IO,为了解决这个瓶颈,于是出现了缓存,比如现在用的最多的 memcached(简称mc).首先,用户访问mc,如果未命中,就 ...
- eclipse修改某一个项目的字符编码
eclipse修改某一个项目的字符编码 1 选中要修改编码的文件,鼠标右键,选择[Properties] 2 左侧选中[Resource], 右侧出现[Text file encoding], ...
- ASP.NET中MessageBox的实现
asp.net中没有MessageBox这个控件,固然可以插入Winform里的MessageBox,但一般不提倡,所以只能变通实现,主要有这几种方法: 1.直接利用javascript的alert和 ...