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在线编辑器 三 . ...
随机推荐
- 脚踏实地学C#3-装箱和拆箱
装箱:一种接受值类型的值,根据这个值在堆中创建一个完整的引用类型对象并返回对象的引用(堆地址)的隐式转换 int i_number = 2; //在栈中声明int类型i_Number变量并初始化 ob ...
- codevs 3012 线段覆盖4
传送门 3012 线段覆盖 4 时间限制: 1 s 空间限制: 64000 KB 题目等级 : 黄金 Gold 题目描述 Description 数轴上有n条线段,线段的两端都是整数坐标,坐 ...
- AOP原理
AOP(面向切面编程):扩展功能时不修改源代码,采用横向抽取机制 纵向抽取机制: 横向抽取机制: 第一种情况: 第二种情况:
- 合并多个cv::Mat类型,即合并多个图片的接口
1. cv::Mat get_merage_image(cv::Mat cur_frame) { cv::Mat image_one=cur_frame; cv::Mat image_two=cur_ ...
- initWithFrame 与 initWithCoder 、awakeFromNib 的方法理解笔记
1. initWithFrame方法是什么? initWithFrame方法用来初始化并返回一个新的视图对象,根据指定的CGRect(尺寸). 当然,其他UI对象,也有initWithFrame方法, ...
- SQL Agent 与 Analysis Server 使用同一个账号
参考网址:http://www.cnblogs.com/wghao/archive/2010/12/21/1912217.html 场景: 部署了一个作业: 第一步:执行一个SSIS 包进行增量更新 ...
- 微信小程序开发之页面数据绑定
js:Page( { data:{ parmer:"", //字符串参数 userinfo:{ userphone:"", ...
- QDUOJ 分辣条-01背包恰好装满情况
分辣条 发布时间: 2016年6月26日 20:36 最后更新: 2016年6月26日 20:37 时间限制: 1000ms 内存限制: 128M 描述 “你喝的酸奶是我买的,辣条也是我买 ...
- STL——stack
首先,堆栈是一个线性表,插入和删除只在表的一端进行.这一端称为栈顶(Stack Top),另一端则为栈底(Stack Bottom).堆栈的元素插入称为入栈,元素的删除称为出栈.由于元素的入栈和出栈总 ...
- 算法学习--Day5
其实今天是第六天,不过昨天写的题目有些杂乱,都是贪心的算法,所以昨天的题目就不放上来了. 今天开始入手数据结构吧啦吧啦.. 数据结构当时学的时候感觉挺简单的,不过现在真正上代码之后发现情况并不妙,还是 ...