zoukankan      html  css  js  c++  java
  • 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':
      blogmigrations001_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:UsersyangxgWorkspacelogproject>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 页页码,这一页需要始终显示。
    2. 第 1 页页码后面的省略号部分。但要注意如果第 1 页的页码号后面紧跟着页码号 2,那么省略号就不应该显示。
    3. 当前页码的左边部分,比如这里的 3-6。
    4. 当前页码,比如这里的 7。
    5. 当前页码的右边部分,比如这里的 8-11。
    6. 最后一页页码前面的省略号部分。但要注意如果最后一页的页码号前面跟着的页码号是连续的,那么省略号就不应该显示。
    7. 最后一页的页码号。

     回顾一下显示分页的步骤,经典的 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。

  • 相关阅读:
    解决Python开发中,Pycharm中无法使用中文输入法问题
    PointNet++作者的视频讲解文字版
    StringBuilder
    DropDownList 添加“请选择”
    SQLServer 2008中SQL增强之三 Merge(在一条语句中使用
    ASP.NET Web Forms 的 DI 應用範例
    怎么设置环境变量
    ParameterizedThreadStart,ThreadStart的使用,线程Thread传参数
    异步删除
    SqlCommandBuilder的作用
  • 原文地址:https://www.cnblogs.com/dion-90/p/8387025.html
Copyright © 2011-2022 走看看