Django博客demo

  Django-blog-demo笔记。

搭建

环境

  python 3.7   Django 2.1.5   pycharm

安装

  cmd里敲:

1
pip install Django==2.1.5

创建项目和应用

创建项目

  在预想安装博客目录下计入cmd,敲:

1
django-admin startproject myblog

  对应目录下生成一个myblog文件夹。

  manage.py:与项目进行交互的命令行工具集的入口

1
python manage.py

  查看所有命令。

  启动命令:

1
python manage.py runserver

  浏览器127.0.0.1:8000查看效果。

  改端口号:

1
python manage.py runserver 8888

myblog目录

  myblog   |–__init__.py   |–settings.py   |–urls.py   |–wsgi.py   manage.py

  wsgi.py   WSGI(Python Web Server Gateway Interface) Python服务器网关接口   Python应用与Web服务器之间的接口

  urls.py   URL配置文件

  settings.py   项目总配置文件,包含数据库、Web应用、时间等各种配置

  __init__.py   内容默认为空

创建应用

  打开命令行,进入manage.py同级目录

1
python manage.py startapp blog

  会多一个blog文件夹。   添加应用名到settings.py中的INSTALLED_APPS里

1
2
3
4
5
6
7
8
9
INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'blog'
]

blog目录

  blog   |–migrations   |—-__init__.py   |–__init__.py   |–admin.py   |–apps.py   |–models.py   |–tests.py   |–views.py

  migrations 数据移植(迁移)模块,内容自动生成

  admin.py 该应用的后台管理系统配置   apps.py 应用配置(Django-1.9以后自动生成)   models.py 数据模块,使用ORM框架,类似于MVC结构中的Models(模型)   test.py 自动化测试模块,在此编写测试脚本(语句)   views.py 执行响应的代码所在模块,代码逻辑处理地(项目大部分代码在此)

Hello World

  打开view.py,输入

1
2
3
4
5
from django.shortcuts import render
from django.http import HttpResponse

def index(request):
    return HttpResponse('Hello World!')

  即编辑blog.views   每个相应对应一个函数,函数必须返回一个响应   函数必须存在一个参数,一般约定为request   每个相应(函数)对应一个URL

在urls.py中,输入

1
2
3
4
5
6
7
8
9
from django.contrib import admin
from django.urls import path

import blog.views as bv

urlpatterns = [
    path('admin/', admin.site.urls),
    path('index/', bv.index),
]

  即编辑urls.py   url函数放在urlpatterns列表中   url函数三个参数:URL(正则),对应方法,名称

  运行,输入地址http://localhost:8000/index/ 即可。

第二种URL配置

  如果页面很多,都写在根urls.py中就很乱。于是,在根urls.py中引入include,在APP目录下创建urls.py文件,格式与根urls.py相同。

  更改后:

1
2
3
4
5
6
7
8
9
from django.contrib import admin
from django.urls import path,include

import blog.views as bv

urlpatterns = [
    path('admin/', admin.site.urls),
    path('index/', include('blog.urls')),
]

  新blog.urls.py

1
2
3
4
5
6
7
from django.urls import path

from . import views

urlpatterns = [
    path('', views.index),
]

Templates

  HTML文件使用了Django模板语言(Django Template Language, DTL)

开发第一个Template

  • 在APP的根目录下创建名叫Templates的目录
  • 在该目录下创建HTML文件
  • 在views.py中返回render()

  html中敲入:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<h1>Hello blog!</h1>
</body>
</html>

  修改views.py为:

1
2
3
4
5
from django.shortcuts import render
from django.http import HttpResponse

def index(request):
    return render(request,'index.html')

  运行查看效果。

DTL初步使用

  render()函数中支持一个dict类型参数   该字典是后台传递到模板的参数,键为参数名   在模板中使用{{参数名}}来直接使用

  修改views.py

1
2
3
...
return render(request,'index.html',{'hello':'Hello blog!'})
...

  修改html

1
2
3
...
<h1>{{hello}}</h1>
...

  运行查看效果。

Models

  通常,一个Model对应数据库的一张数据表   Django中Models以类的形式表现   它包含了一些基本字段以及数据的一些行为

ORM

  对象关系映射(Object Relation Mapping)   实现了对象和数据库之间的映射   隐藏了数据访问的细节,不需要编写SQL语句

编写Models

  • 在应用根目录下创建models.py,并引入models模块
  • 创建类,继承models.Model,该类即是一张数据表
  • 在类中创建字段

字段创建

  字段即类里面的属性(变量)

1
attr = models.CharField(max_length = 64)

生成数据表

  命令行中进入manage.py同级目录   执行命令

1
2
python manage.py makemigrations app名可选
python manage.py migrate

  不加app名默认给所有app进行数据迁移。

  cmd将显示:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
E:\PythonCode\myblog>python manage.py makemigrations
Migrations for 'blog':
  blog\migrations\0001_initial.py
    - Create model Article

E:\PythonCode\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 admin.0003_logentry_add_action_flag_choices... 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 auth.0009_alter_user_last_name_max_length... OK
  Applying blog.0001_initial... OK
  Applying sessions.0001_initial... OK

生成数据表

  查看   Django会自动在app/migrations/目录下生成移植文件   执行命令查看SQL语句

1
python manage.py sqlmigrate 应用名 文件id

  cmd将显示:

1
2
3
4
5
6
7
E:\PythonCode\myblog>python manage.py sqlmigrate blog 0001
BEGIN;
--
-- Create model Article
--
CREATE TABLE "blog_article" ("id" integer NOT NULL PRIMARY KEY AUTOINCREMENT, "title" varchar(32) NOT NULL, "content" text NULL);
COMMIT;

  默认sqlite3的数据库在项目根目录下db.sqlite3   查看并编辑db.sqlite3,使用第三方软件,如SQLite Expert Personal

页面呈现数据

后台步骤

  views.py中import models

1
2
article = models.Article.objects.get(pk = 1)
render(request, page, {'article':article})

后端步骤

  模板可直接使用对象以及对象的“.”操作 {{article}}

  修改html

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<h1>{{article.title}}</h1>
<h3>{{article.content}}</h3>
</body>
</html>

  运行,查看http://localhost:8000/index/

Admin

Django自带的一个功能强大的自动化数据管理界面 被授权的用户可直接在Admin中管理数据库 Django提供了许多针对Admin的定制功能

配置Admin

创建用户

创建超级用户

1
python manage.py createsuperuser

之后要求输入用户名 邮箱 密码

Admin入口访问地址:localhost:8000/admin/

如需修改成中文版,修改settings.py中LANGUAGE_CODE = ‘zh_Hans’ (英文:LANGUAGE_CODE = ’en-us’)

配置应用

在应用下admin.py中引入自身的models模块(或里面的模型类) 编辑admin.py

1
2
from .models import Article
admin.site.register(models.Article)

修改数据

点击Article超链接进入Article列表页面,按页面指示修改。

修改数据默认显示名称

每条都显示的Article object,很不方便,显示文章标题比较好。

  • 在Article类下添加一个方法
  • 根据Python版本选择__str__(self) (python3以上)或__unicode__(self) (python2.7)
  • return self.title

博客开发

页面设计

  博客主页面   博客文章内容页面   博客撰写页面

主页面内容

  文章标题列表,超链接   发表博客按钮(超链接)

列表编写思路

  • 取出数据库中所有文章对象
  • 将文章对象们打包成列表,传递到前端
  • 前端页面把文章以标题超链接的形式逐个列出

  模板For循环

1
2
3
{%for xx in xxs%}
# HTML语句
{%endfor%}

  修改views.py

1
2
3
4
5
6
7
from django.shortcuts import render
from django.http import HttpResponse

from . import models
def index(request):
    articles = models.Article.objects.all()
    return render(request,'index.html',{'articles': articles})

  修改html

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<h1>
    <a href="">新文章</a>
</h1>
{% for article in articles %}
    <a href="">{{article.title}}</a>
    <br/>
{% endfor %}
</body>
</html>

页面内容

  标题   文章内容   修改文章按钮(超链接)

  在templates中新增article_page.html

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Article Page</title>
</head>
<body>
<h1>{{article.title}}</h1>
<br/>
<h3>{{article.content}}</h3>
<br/><br/>
<a href="">修改文章</a>
</body>
</html>

  修改views.py

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
from django.shortcuts import render
from django.http import HttpResponse

from . import models
def index(request):
    articles = models.Article.objects.all()
    return render(request,'index.html',{'articles': articles})

def article_page(request, article_id):
    article=models.Article.objects.get(pk = article_id)
    return render(request,'article_page.html',{'article':article})
``
### URL传递参数
  参数写在相应函数中request后可以有默认值

  修改blog下的urls.py
```py
from django.urls import path

from . import views

urlpatterns = [
    path('', views.index),
    path('article/<article_id>', views.article_page),
]

  顺便把myblog\urls.py里的index改成blog(非必要,只是更符合博客url)

1
2
3
4
5
6
7
8
9
from django.contrib import admin
from django.urls import path,include

import blog.views as bv

urlpatterns = [
    path('admin/', admin.site.urls),
    path('blog/', include('blog.urls')),
]

  运行,输入http://localhost:8000/blog/article/1 查看。

超链接

  href后是目标地址,template中可用

1
{%url 'app_name:url_name' param%}

  其中app_name和url_name都在url中配置

再配URL

uel函数的名称参数

  法一:根urls,写在include()的第二个参数位置,namespace='blog'   法二:应用下则写在url()的第三个参数位置,name='article'   主要取决于是否使用include引用了另一个url配置文件

撰写页面

  标题编辑栏   文章内容编辑区域   提交按钮

  新建edit_page.html

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Edit Page</title>
</head>
<body>
<form action="" method="post">
    <label>文章标题
    <input type="text" name="title"/>
    </label>
    <br/>
      <label>文章内容
    <input type="text" name="content"/>
    </label>
    <br/>
    <input type="submit" value="提交"/>
</form>
</body>
</html>

  views.py新增

1
2
def edit_page(request):
    return render(request,'edit_page.html')

  blog\urls.py新增

1
    path('edit', views.edit_page),

  运行,输入http://localhost:8000/blog/edit 查看。

编辑相应函数

  使用request.POST['参数名']获取表单数据   models.Article.objects.create(title, content)创建对象

两个编辑页面

  思路:新文章为空,修改文章有内容   修改文章页面有文章对象   文章的ID

  修改数据   article.title = title   article.save()

  修改views.py

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
def edit_page(request, article_id):
    if str(article_id) == '0':
        return render(request,'edit_page.html')
    article = models.Article.objects.get(pk=article_id)
    return render(request, 'edit_page.html', {'article': article})


def edit_action(request):
    title = request.POST.get('title', 'TITLE')
    content = request.POST.get('content', 'CONTENT')
    article_id = request.POST.get('article_id', '0')

    if article_id == '0':
        models.Article.objects.create(title=title, content=content)
        articles = models.Article.objects.all()
        return render(request, 'index.html', {'articles': articles})

    article = models.Article.objects.get(pk=article_id)
    article.title = title
    article.content = content
    article.save()
    return render(request,'article_page.html', {'article': article})

  修改blog\urls.py

1
2
3
4
5
6
urlpatterns = [
    path('', views.index),
    path('article/(?P<article_id>[0-9]+)$', views.article_page,name='article_page'),
    path('edit/(?P<article_id>[0-9]+)$', views.edit_page,name='edit_page'),
    path('edit/Action$', views.edit_action,name='edit_action'),
]

  修改article_page.html

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Article Page</title>
</head>
<body>
<h1>{{article.title}}</h1>
<br/>
<h3>{{article.content}}</h3>
<br/><br/>
<a href="{% url 'blog:edit_page' article.id %}">修改文章</a>
</body>
</html>

  修改主页index.html

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<h1>
    <a href="{% url 'blog:edit_page' 0 %}">新文章</a>
</h1>
{% for article in articles %}
    <a href="{% url 'blog:article_page' article.id %}">{{article.title}}</a>
    <br/>
{% endfor %}
</body>
</html>

  修改edit_page.gtml

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Edit Page</title>
</head>
<body>
<form action="{% url 'blog:edit_action' %}" method="post">
    {% csrf_token %}
    {% if article %}
        <input type="hidden" name="article_id" value="{{article.id}}"/>
        <label>文章标题
            <input type="text" name="title" value="{{article.title}}"/>
        </label>
        <br/>
        <label>文章内容
            <input type="text" name="content" value="{{article.content}}"/>
        </label>
        <br/>
    {% else %}
        <input type="hidden" name="article_id" value="0"/>
        <label>文章标题
            <input type="text" name="title"/>
        </label>
        <br/>
        <label>文章内容
            <input type="text" name="content"/>
        </label>
        <br/>
    {% endif %}
    <input type="submit" value="提交">
</form>
</body>
</html>

Templates过滤器

  写在模板中,属于Django模板语言   可以修改模板中的变量,从而显示不同的内容   使用

1
{{value | filter}}

e.g.

1
{{list_nums | length}}

  过滤器可叠加:

1
{{value | filter1 | filter2 | ...}}

  修改edit_page.html

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Edit Page</title>
</head>
<body>
<form action="{% url 'blog:edit_action' %}" method="post">
    {% csrf_token %}
        <input type="hidden" name="article_id" value="{{article.id | default:'0'}}"/>
        <label>文章标题
            <input type="text" name="title" value="{{article.title}}"/>
        </label>
        <br/>
        <label>文章内容
            <input type="text" name="content" value="{{article.content}}"/>
        </label>
        <br/>
    <input type="submit" value="提交">
</form>
</body>
</html>

Django Shell

  Python交互式命令行程序,自动引入了项目环境,可使用它与项目进行交互   使用

1
2
3
python manage.py shell
from blog.models import Article
Article.objects.all()

  可以使用它进行调试   测试未知的方法

Admin增强

创建admin配置类

  class ArticleAdmin(admin.ModelAdmin)   注册:admin.site.register(Article, ArticleAdmin)

显示其他字段

  list_display = (’title’, ‘content’)   list_display同时支持tuple和list

  修改admin.py

1
2
3
4
5
6
7
8
from django.contrib import admin

from .models import Article

class ArticleAdmin(admin.ModelAdmin):
    list_display = ('title', 'content','pub_time')

admin.site.register(Article, ArticleAdmin)

  修改models.py

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
from django.db import models


class Article(models.Model):
    title = models.CharField(max_length=32, default='Title')
    content=models.TextField(null=True)
    pub_time = models.DateTimeField(auto_now=True)

    def __str__(self):
        return self.title

  如果是

1
pub_time = models.DateTimeField(null=True)

  则可自己设定时间。

  修改完代码记得进行数据移植

1
2
python manage.py makemigrations
python manage.py migrate

过滤器

  list_filter = (‘pub_time’,)   注意有个逗号

相关资料

Django API Reference

代码下载

django-blog-demo


hexo天坑: 遇到 两个大括号 以及 一个大括号一个% 一定放入代码行(如下),这样是不行的

1
2
{{}}
{%%}

排查这个bug花了我半个小时…

Licensed under CC BY-NC-SA 4.0
最后更新于 0001-01-01 00:00 UTC
使用 Hugo 构建
主题 StackJimmy 设计