Django学习小组出品:一起来做一个简单的Blog第一周文档(教程)

本节是 django blog 项目的开篇,是 django 学习小组的集体学习成果。django学习小组是由我发起的一个促进 django 新手互相学习、互相帮助的组织。小组在一边学习 django 的同时将一起完成三个项目:

  • 一个简单django blog,用于发布小组每周的学习和开发文档
  • django中国社区,为国内的 django 开发者们提供一个长期维护的 django 社区,聚集全国的 django 开发者到这个社区上来
  • django 问答社区, 类似于segmentfault 和 stackoverflow但更加专注(只专注于 django 开发的问题)的问答社区

目前小组正在完成第一个项目,本文即是该项目第一周的相关文档。

更多的信息请关注我们的 github 组织首页,本教程项目的相关源代码也已上传到 github 上。

同时,你也可以加入我们的邮件列表 [email protected] ,随时关注我们的动态,我们会将每周的详细开发文档和代码通过邮件列表发出。

如有任何建议,欢迎提 Issue,欢迎fork,pull request,当然也别忘了 Starred 哦!

每周更新,敬请关注

Django开发环境的搭建和创建Blog工程

django 的开发环境搭建以及如何创建工程在网上有大量的博客和教程介绍,在此不再重复说明。但我建议最好的参考资料还是Django官方的入门 Tutorials ,即官方文档First steps 部分的六个 Parts。当然如果你不喜欢英文,可以看网友的翻译版本:Django1.8.2中文文档入门部分。

要开始 Django 开发,你需要从中掌握以下知识:

  • 如何创建 Django 工程,并了解 Django 默认的工程目录结构
  • 如何创建 Django APP
  • 理解 Django 的MTV 模式,学会编写 Model、View、Template
  • Django 如何处理静态文件,即各种 CSS,JS,以及图片文件等

Django应用是如何工作的?

先看一张流程图,再来逐步讲解其过程:

1:用户通过浏览器输入相应的 URL 发起 HTTP请求(一般是 GET/POST)

2:django 接受到请求,检测 urls.py 文件,找到和用户输入的 URL 相匹配的项,并调用该 URL 对应的视图函数(view),例如,通常来说 urls.py 文件里的代码是这样的:


url(r‘^homepage/$‘, views.home_page)

则当用户输入的 URL 为 www.某个网址.com/homepage 时,django 检测到该 URL 与上面的代码 匹配,于是调用后面的 views.home_page 视图函数,把相应的请求交给该视图函数处理。

3:视图函数被调用后,可能会访问数据库(Model)去查询用户想要请求的数据,并加载模板文件(Template),渲染完数据后打包成 HttpResponse 返回给浏览器(Http协议)

大致工作流程就是这样,从流程可以看出,我们需要做的就是:

  • 编写相应的 url
  • 编写数据库(Model)
  • 编写处理 Http 请求的视图函数(View)
  • 编写需要渲染的模板(Template)

这就是 Django 开发的最主要工作,下面遵循这样的开发流程开始编写我们的 Blog程序吧。

编写 Model

Model 对应数据库,我们编写的是一个 Blog 应用,因此数据库中应该存放 Blog 下的文章(Aticle),文章由标题(title)、正文(body)、发布时间(publised_time)等组成。先看 django 是如何定义数据库的,之后再逐行解释代码(假设你已经对 django 的工程目录结构了解了,我们一般把 Model 定义在 models.py 文件中):

models.py

from django.db import models

class Article(models.Model):
    STATUS_CHOICES = (
        (‘d‘, ‘Draft‘),
        (‘p‘, ‘Published‘),
    )

    title = models.CharField(‘标题‘, max_length=70)
    body = models.TextField(‘正文‘)
    created_time = models.DateTimeField(‘创建时间‘, auto_now_add=True)
    last_modified_time = models.DateTimeField(‘修改时间‘, auto_now=True)
    status = models.CharField(‘文章状态‘, max_length=1, choices=STATUS_CHOICES)
    abstract = models.CharField(‘摘要‘, max_length=54, blank=True, null=True,
                                help_text="可选,如若为空将摘取正文的前54个字符")
    views = models.PositiveIntegerField(‘浏览量‘, default=0)
    likes = models.PositiveIntegerField(‘点赞数‘, default=0)
    topped = models.BooleanField(‘置顶‘, default=False)

    category = models.ForeignKey(‘Category‘, verbose_name=‘分类‘,
                                 null=True,
                                 on_delete=models.SET_NULL)

    def __str__(self):
        return self.title

    class Meta:
        ordering = [‘-last_modified_time‘]

class Category(models.Model):
    name = models.CharField(‘类名‘, max_length=20)
    created_time = models.DateTimeField(‘创建时间‘, auto_now_add=True)
    last_modified_time = models.DateTimeField(‘修改时间‘, auto_now=True)

    def __str__(self):
        return self.name

逐行解释:

from django.db import models
# 和 model 相关的一些API定义在 django.db.models 模块中

class Article(models.Model):
    """
    所有的 model 必须继承自django.db.models
    类 Aticle 即表示 Blog 的文章,一个类被 diango 映射成数据库中对应的一个表,表名即类名
    类的属性(field),比如下面的 title、body 等对应着数据库表的属性列
    """
    STATUS_CHOICES = (
        (‘d‘, ‘Draft‘),
        (‘p‘, ‘Published‘),
    )
    # 在 status 时说明

    title = models.CharField(‘标题‘, max_length=70)
    # 文章标题,CharField 表示对应数据库中表的列是用来存字符串的,‘标题‘是一个位置参数
    #(verbose_name),主要用于 django 的后台系统,不多做介绍。max_length 表示能存储的字符串
    # 的最大长度

    body = models.TextField(‘正文‘)
    # 文章正文,TextField 用来存储大文本字符

    created_time = models.DateTimeField(‘创建时间‘, auto_now_add=True)
    # 文章创建时间,DateTimeField用于存储时间,设定auto_now_add参数为真,则在文章被创建时会自        动添加创建时间

    last_modified_time = models.DateTimeField(‘修改时间‘, auto_now=True)
    # 文章最后一次编辑时间,auto_now=True表示每次修改文章时自动添加修改的时间

    status = models.CharField(‘文章状态‘, max_length=1, choices=STATUS_CHOICES)
    # STATUS_CHOICES,field 的 choices 参数需要的值,choices选项会使该field在被渲染成form时      被渲染为一个select组件,这里我定义了两个状态,一个是Draft(草稿),一个是Published(已发布),select组件会有两个选项:Draft 和 Published。但是存储在数据库中的值分别是‘d‘和‘p‘,这就是 choices的作用。

    abstract = models.CharField(‘摘要‘, max_length=54, blank=True, null=True,
                                help_text="可选,如若为空将摘取正文的前54个字符")
    # 文章摘要,help_text 在该 field 被渲染成 form 是显示帮助信息

    views = models.PositiveIntegerField(‘浏览量‘, default=0)
    # 阅览量,PositiveIntegerField存储非负整数

    likes = models.PositiveIntegerField(‘点赞数‘, default=0)
    # 点赞数

    topped = models.BooleanField(‘置顶‘, default=False)
    # 是否置顶,BooleanField 存储布尔值(True或者False),默认(default)为False

    category = models.ForeignKey(‘Category‘, verbose_name=‘分类‘,
                                 null=True,
                                 on_delete=models.SET_NULL)
    # 文章的分类,ForeignKey即数据库中的外键。外键的定义是:如果数据库中某个表的列的值是另外一个表的主键。外键定义了一个一对多的关系,这里即一篇文章对应一个分类,而一个分类下可能有多篇    文章。详情参考django官方文档关于ForeinKey的说明,on_delete=models.SET_NULL表示删除某个分类(category)后该分类下所有的Article的外键设为null(空)

    def __str__(self):
        # 主要用于交互解释器显示表示该类的字符串
        return self.title

    class Meta:
        # Meta 包含一系列选项,这里的 ordering 表示排序,- 号表示逆序。即当从数据库中取出文章时,其是按文章最后一次修改时间逆序排列的。
        ordering = [‘-last_modified_time‘]

class Category(models.Model):
    """
    另外一个表,存储文章的分类信息
    """
    name = models.CharField(‘类名‘, max_length=20)
    created_time = models.DateTimeField(‘创建时间‘, auto_now_add=True)
    last_modified_time = models.DateTimeField(‘修改时间‘, auto_now=True)

    def __str__(self):
        return self.name

由上可见,设计数据库结构就是编写 models,数据库中每一个实体对应的表在 django 中对用着 models.py 中的一个类,类的属性对应着数据库表的属性列。

model 定义完毕后,运行以下命令即可生成相应的数据库:

python manage.py makemigrations

python manage.py migrate

你可以打开相应的数据库文件看看里面生成的表结构,加深理解。

其中以上的代码中涉及到一些 django 相关的概念,分别给出以下参考资料供学习:

编写 View

上面已经介绍了 django 应用的工作流程,数据库建立完毕后需要编写视图函数(view)来处理 Http 请求。同样先来看 django 的 view 代码是如何写的,然后我们再逐行解释。

我们现在要设计的是一个首页的视图函数,即用户进入我们的 Blog 首页后,我们需要把数据库中存储的文章的相关信息取出来展示给用户看:

views.py

from django.views.generic.list import ListView
from blog.models import Article, Category
import markdown2

class IndexView(ListView):
    template_name = "blog/index.html"
    context_object_name = "article_list"

    def get_queryset(self):
        article_list = Article.objects.filter(status=‘p‘)
        for article in article_list:
            article.body = markdown2.markdown(article.body, )
        return article_list

    def get_context_data(self, **kwargs):
        kwargs[‘category_list‘] = Category.objects.all().order_by(‘name‘)
        return super(IndexView, self).get_context_data(**kwargs)

逐行解释:

from blog.models import Article
from blog.models import Category
from django.views.generic import ListView
import markdown2

class IndexView(ListView):
    """
    首页视图,继承自ListVIew,用于展示从数据库中获取的文章列表
    """

    template_name = "blog/index.html"
    # template_name属性用于指定使用哪个模板进行渲染

    context_object_name = "article_list"
    # context_object_name属性用于给上下文变量取名(在模板中使用该名字)

    def get_queryset(self):
        """
        过滤数据,获取所有已发布文章,并且将内容转成markdown形式
        """
        article_list = Article.objects.filter(status=‘p‘)
        # 获取数据库中的所有已发布的文章,即filter(过滤)状态为‘p‘(已发布)的文章。
        for article in article_list:
            article.body = markdown2.markdown(article.body, )
            # 将markdown标记的文本转为html文本
        return article_list

    def get_context_data(self, **kwargs):
        # 增加额外的数据,这里返回一个文章分类,以字典的形式
        kwargs[‘category_list‘] = Category.objects.all().order_by(‘name‘)
        return super(IndexView, self).get_context_data(**kwargs)

可能觉得奇怪的是既然是视图函数为什么不是用 def 来定义,而是写成一个类?这里涉及到 django 的关于类的通用视图的概念:参考类的通用视图。我们通过调用 as_view 方法会将该类视图转为一般的视图,这在 url 部分会介绍。

这样,这个视图的工作流程就是首先接受来自用户的 Http 请求,然后从数据库中获取到已经发布的文章列表:article_list = Article.objects.filter(status=‘p‘),并转换 markdown 语法标记,再加载模板文件:template_name = "blog/index.html",将模板中的变量用相应的数据库中的数据库替换后返回给浏览器,这样,用户就看到了从数据库中被取出然后被渲染后的文章列表了。

编写 Template

template 稍微麻烦一点,因为涉及到 html 的相关知识,如果你没有学过 html ,可能会有些看不懂,因此推荐学习一下,这里有很棒的教程:w3school 的 html 教程供学习使用。这里只介绍一点点本项目涉及的模板相关知识,其实 django 文档的入门教程的六个 parts 中涵盖的点已经足以对付此简单的 Blog 项目了。

  • 模板标签,用{% %} 表示,一些常用的有{% for %}循环标签,{% if %}判断标签等。
  • 模板变量,用{{ variable }}表示,模板渲染是这些变量会被数据库中相应的值代替,例如article_list = Article.objects.filter(status=‘p‘),从数据库中取出了已发布的文章列表,赋给了 article_list 变量。如果模板文件中有如下代码:

{% for article in article_list %}
    {{article.title}}

那么渲染时就会循环渲染 n 篇文章,并且 {{article.title}} 也会被存储在数据库中文章的标题取代。

更多详细的资料,请参考官方文档关于 template 的介绍,或者中文文档

编写 URL

写好了数据库、视图和模板,现在就是当用户在浏览器输入 url 访问我们的 Blog 时要告诉 django 哪个 url 的请求对应哪个视图函数来处理,通过 urls.py 来指定:


urls.py

urlpatterns = [

    ...
    url(r‘^blog/‘, views.IndexView.as_view()),
    # 首页调用IndexView
    ...

]

至此,Blog 应用的首页算是完成了,当用户访问我们的主页就可以看到文章列表了:

结束语

本节是 django blog 项目的开篇,是 django 学习小组的集体学习成果。django学习小组是由我发起的一个促进 django 新手互相学习、互相帮助的组织。小组在一边学习 django 的同时将一起完成三个项目:一个简单django blog,用于发布小组每周的学习和开发文档;django中国社区,为国内的 django 开发者们提供一个长期维护的 django 社区,聚集全国的 django 开发者到这个社区上来。类似于segmentfault 和 stackoverflow但更加专注(只专注于 django 开发的问题)的django 问答社区。目前小组正在完成第一个项目,本文即是该项目第一周的相关文档。

更多的信息请关注我们的 github 组织首页,本教程项目的相关源代码也已上传到 github 上。

同时,你也可以加入我们的邮件列表 [email protected] ,随时关注我们的动态,我们会将每周的详细开发文档和代码通过邮件列表发出。

如有任何建议,欢迎提 Issue,欢迎fork,pull request,当然也别忘了 Starred 哦!

时间: 2024-08-04 18:29:22

Django学习小组出品:一起来做一个简单的Blog第一周文档(教程)的相关文章

【WPF】学习笔记(一)——做一个简单的电子签名板

参加实习(WPF)已经有两个多周的时间了,踩了一些坑,也算积累了一些小东西,准备慢慢拿出来分享一下.(●'?'●) 这次呢就讲讲一个简单的电子签名板的实现. 先上张图(PS:字写得比较丑,不要太在意哈): 1.任务目标 最基本的需求:1.签名功能 2.清除签名 3.保存签名(让用户选择文件夹.签名保存为PNG格式的图片) 尝试额外功能:1.Ctrl + Z实现撤销功能 2.Ctrl + Y实现重做功能 3.保存签名后打开文件位置并选中文件 2.搞事情 1)UI方面 如图,总体来说,一个InkCa

[3] 用D3.js做一个简单的图表吧!

本人的个人博客为: www.ourd3js.com csdn博客为: blog.csdn.net/lzhlzz 转载请注明出处,谢谢. 前面说了几节,都是对文字进行处理,这一节中将用 D3.js 做一个简单的柱形图. 做柱形图有很多种方法,比如用 HTML 的 div 标签,或用 svg . 推荐用 SVG 来做各种图形.SVG 意为可缩放矢量图形(Scalable Vector Graphics),SVG 使用 XML 格式定义图像,不清楚什么是SVG的朋友请先在 w3cschools 学习下

使用React并做一个简单的to-do-list

1. 前言 说到React,我从一年之前就开始试着了解并且看了相关的入门教程,而且还买过一本<React:引领未来的用户界面开发框架 >拜读.React的轻量组件化的思想及其visual-dom的这种技术创新,也算是早就有了初步了解.一来没有学的太深入,二来后来在工作中和业余项目中都没有用到,因此慢慢的就更加生疏了. 近期,因为我想把自己的开源项目wangEditor能放在React.angular和vuejs中使用.先从react开始,顺手自己也重试一下React的基础知识,顺便再做一个小d

【 D3.js 入门系列 — 3 】 做一个简单的图表!

图1. 柱形图 1. 柱形图 前几章的例子,都是对文字进行处理.本章中将用 D3 做一个简单的柱形图.制作柱形图有很多种方法,比如用 HTML 的 <div> 标签,或在 SVG 上绘制 . SVG ,即可缩放矢量图形(Scalable Vector Graphics),使用 XML 格式定义图形,可在 W3School 学习 SVG 的相关语法,不需要记住所有标签,用的时候再查即可. 先看下面的代码: <script src="http://d3js.org/d3.v3.mi

使用Multiplayer Networking做一个简单的多人游戏例子-2/3(Unity3D开发之二十六)

猴子原创,欢迎转载.转载请注明: 转载自Cocos2Der-CSDN,谢谢! 原文地址: http://blog.csdn.net/cocos2der/article/details/51007512 使用Multiplayer Networking做一个简单的多人游戏例子-1/3 使用Multiplayer Networking做一个简单的多人游戏例子-2/3 使用Multiplayer Networking做一个简单的多人游戏例子-3/3 7. 在网络中控制Player移动 上一篇中,玩家操

Android学习路线(四)构建一个简单的UI

Android应用的图形化用户界面的构建使用的是View 和 ViewGroup 对象的层次嵌套. View 对象通常是UI部件,例如 buttons 或者 text fields ,而 ViewGroup 是用来定义它的子布局如何排布的容器,它通常是不可见的,例如一个网格或者一个垂直的列表. Android提供XML词汇与View或者ViewGroup的子类的对应,这样的话你就可以通过XML元素的层级嵌套来定义你的UI. 另一种布局 使用XML声明UI比在运行时代码中声明更有用处可以在很多地方

用EF DataBase First做一个简单的MVC3报名页面

使用EF DataBase First做一个简单的MVC3报名网站 ORM(Object Relational Mapping)是面向对象语言中的一种数据访问技术,在ASP.NET中,可以通过ADO.NET Entity Framework技术来简化数据访问.在EF里,有Code First,Model First和DataBase First三种方法来实现. 百度百科关于ORM的介绍: http://baike.baidu.com/view/197951.htm?fr=aladdin 1.就像

【Python】 做一个简单的 http 服务器

# coding=utf-8 ''' Created on 2014年6月15日 @author: Yang ''' import socket import datetime # 初始化socket s = socket.socket() # 获取主机名, 也可以使用localhost # host = socket.gethostname() host = "localhost" # 默认的http协议端口号 port = 80 # 绑定服务器socket的ip和端口号 s.bin

Jmeter初步使用二--使用jmeter做一个简单的性能测试

经过上一次的初步使用,我们懂得了Jmeter的安装与初步使用的方法.现在,我们使用Jmeter做一个简单的性能测试.该次测试,提交的参数不做参数化处理,Jmeter各元件使用将在介绍在下一博文开始介绍并使用. 首先,打开Jmeter工具,并建立一个测试计划(测试脚本).启动jmeter后,jmeter会自动生成一个空的测试计划,我们可以基于该测试计划建立自己的测试计划. 步骤: 步骤一:添加线程组 一个性能测试请求负载是基于一个线程组完成的.一个测试计划必须有一个线程组.测试计划添加线程组非常简