Django 搭建简易博客

简易博客开发

这篇博客摘自《Python 核心编程》(第三版)

一、安装

pip install Django==1.10.8

二、使用 django-admin.py 工具创建项目

在 POSIX 平台上,一般位于/usr/local/bin,/usr/bin 这样的目录中
在 Windows 系统中,一般位于 Python 安装目录 Scripts 文件夹下

进入项目所在目录

django-admin startproject mysite # POSIX 中为 django-admin.py startproject mysite

测试是否可以运行

cd mysite
python manage.py runserver 8080

如果出现 ‘It worked!’ 则成功
Ctrl + C 退出测试

三、创建应用

python manage.py startapp blog

添加应用,在 settings.py 中配置
INSTALLED_APPS = [
    ...
    'blog',
]

四、必要配置

配置语言和时区,在 settings.py 中配置
LANGUAGE_CODE = 'zh-Hans'
TIME_ZONE = 'Asia/Shanghai'
配置数据库,在 settings.py 中配置,然后手动创建数据库
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'testdb',
        'USER': 'root',
        'PASSWORD': '123456',
        'HOST': 'localhost',
        'PORT': '3306',
    }
}

五、创建表或更改表结构

添加模型,在 blog 的 models.py 中添加
from django.db import models

# Create your models here.
class BlogPost(models.Model):
    title = models.CharField(max_length=150)
    body = models.TextField()
    timestamp = models.DateTimeField()
创建表或更改表结构

Django 1.7.1及以上 用以下命令
1. 创建更改的文件
python manage.py makemigrations
2. 将生成的py文件应用到数据库
python manage.py migrate

旧版本的Django 1.6及以下用
python manage.py syncdb

六、Django 管理应用

在 settings.py 的 INSTALLED_APPS 中,有 ‘django.contrib.admin’, 表明默认启用了admin
在urls.py 中,默认开启了其url的访问

from django.conf.urls import url
from django.contrib import admin

urlpatterns = [
    url(r'^admin/', admin.site.urls),
]
在 blog 的 admin.py 中注册 BlogPost
from django.contrib import admin
from blog import models

# Register your models here.
admin.site.register(models.BlogPost)
创建超级管理员

python manage.py createsuperuser # 按照提示输入用户名和对应的密码就好了邮箱可以留空,用户名和密码必填
修改用户密码:
python manage.py changepassword username

访问 admin 页面

python manage.py runserver 8080
访问:http://localhost:8080/admin

这里写图片描述

填写创建的超级用户名和密码,登录后看到 admin 主页

这里写图片描述
尝试添加 BlogPost 数据
点击 BLOG / Blog posts,可以看到目前的数据

这里写图片描述
点击右上角 Add blog post + ,添加数据

这里写图片描述
保存后,增加一条记录

这里写图片描述
再添加一条记录

这里写图片描述
这里写图片描述
新的 BlogPost 名称也是一样的,这是admin的默认设置,可以进行更改

# admin.py 
from django.contrib import admin
from blog import models

# Register your models here.
class BlogPostAdmin(admin.ModelAdmin):
    list_display = ('title', 'timestamp')

admin.site.register(models.BlogPost, BlogPostAdmin)

更改后的页面

这里写图片描述
进入用户页面

这里写图片描述
这里写图片描述
这里写图片描述

七、创建博客的用户界面

创建URL模式
# mysite/urls.py

from django.conf.urls import url, include
from django.contrib import admin
from blog import views as blog_views

urlpatterns = [
    url(r'^$', blog_views.index, name='index'),
    url(r'^blog/', include('blog.urls', namespace='blog')),
    url(r'^admin/', admin.site.urls),
]


# blog/urls.py

from django.conf.urls import url
from . import views as blog_views

urlpatterns = [
    url(r'^$', blog_views.archive, name='show'),
]
创建视图
# blog/views.py

from datetime import datetime
from django.shortcuts import render
from blog.models import BlogPost

# Create your views here.

def index(request):
    return HttpResponseRedirect('/blog/')

def archive(request):
    posts = BlogPost.objects.all()
    return render(request, 'archive.html', {'posts': posts})
创建模板
# blog/templates/archive.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Blog</title>
</head>
<body>
{% for post in posts %}
    <h2>{{ post.title }}</h2>
    <p>{{ post.timestamp }}</p>
    <p>{{ post.body }}</p>
    <hr>
{% endfor %}
</body>
</html>

访问 http://localhost:8080/blog/

这里写图片描述

更改默认排序,在模型中增加Meta内部类
# blog/models.py

from django.db import models

# Create your models here.

class BlogPost(models.Model):
   title = models.CharField(max_length=150)
   body = models.TextField()
   timestamp = models.DateTimeField()

   class Meta:
      ordering = ('-timestamp',)

这里写图片描述

目前用户只可以查看博客,还需要增加添加博客页面
增加 URL 配置
# blog/urls.py
from . import views as blog_views

urlpatterns = [
    ...
    url(r'^create/$', blog_views.create_blog, name='create')
]
视图中增加创建博客函数
# blog/views.py
from django.http import HttpResponseRedirect

def create_blog(request):
    if request.method == 'POST':
        BlogPost(
            title=request.POST.get('title'),
            body=request.POST.get('body'),
            timestamp=datetime.now(),
        ).save()

    return HttpResponseRedirect('/blog/')

# 页面中增加提交博客代码,需要增加 {% csrf_token %} 不然返回 403 错误

# blog/templates/archive.html

<!DOCTYPE html>
...
<body>
<form action="/blog/create/" method="post">
    {% csrf_token %}
    Title:
    <input type="text" name="title"><br>
    Body:
    <textarea name="body" rows="3" cols="60"></textarea><br>
    <input type="submit">
</form>
<hr>
...
</body>
</html>

这里写图片描述

八、模型表单

目前初步完成简易博客,但现有代码有以下问题:
1、处理的数据来源于模型字段,而表单和视图函数均与其直接关联;
2、当模型变化后,所有的都需要改变;并且,重复的代码较多。

<input type="text" name="title"><br>
<textarea name="body" rows="3" cols="60"></textarea><br>
BlogPost(
    title=request.POST.get('title'),
    body=request.POST.get('body'),
    timestamp=datetime.now(),
).save()
使用Django的模型表单可以解决这个问题
# blog/models.py 中增加如下代码
from django import forms

class BlogPostForm(forms.Form):
   title = forms.CharField(max_length=150)
   body = forms.CharField(
      widget=forms.Textarea(attrs={'rows':3, 'cols':60})
   )
这样还是与模型重复,而这里表单字段与模型一致,所以可以简化
class BlogPostForm(forms.ModelForm):
   class Meta:
      model = BlogPost
      exclude = ('timestamp',) # timestamp不是通过表单提交的,放在 exclude 中
使用ModelForm生成页面
# blog/views.py

from blog.models import BlogPost, BlogPostForm

def archive(request):
    posts = BlogPost.objects.all()
    return render(request, 'archive.html', {'form': BlogPostForm(), 'posts': posts})

# blog/templates/archive.html

...
<form action="/blog/create/" method="post">
    {% csrf_token %}
    <table>{{ form }}</table><br>
    <input type="submit">
</form>
...
处理 ModelForm 数据
# blog/views.py

from blog.models import BlogPostForm

def create_blog(request):
    if request.method == 'POST':
        form = BlogPostForm(request.POST)
        if form.is_valid():
            post = form.save(commit=False)  # commit为False,不立即提交
            post.timestamp = datetime.now()
            post.save() # 只有此时提交才有效

    return HttpResponseRedirect('/blog/')

修改后的效果

这里写图片描述

九、*单元测试

# blog/test.py

from datetime import datetime
from django.test import TestCase
from django.test.client import Client
from blog.models import BlogPost

# Create your tests here.

class BlogPostTest(TestCase):
    def test_obj_create(self):
        BlogPost.objects.create(title='raw title', body='raw body', timestamp=datetime.now())
        self.assertEqual(1, BlogPost.objects.count())
        self.assertEqual('raw title', BlogPost.objects.get(id=1).title)

    def test_home(self):
        response = self.client.get('/blog/')
        self.failUnlessEqual(response.status_code, 200)

    def test_slash(self):
        response = self.client.get('/')
        self.assertIn(response.status_code, (301, 302))

    def test_empty_create(self):
        response = self.client.get('/blog/create/')
        self.assertIn(response.status_code, (301, 302))

    def test_post_create(self):
        c = Client()
        response = c.post('/blog/create/', {
            'title': 'post title',
            'body': 'post body'
        })
        self.assertIn(response.status_code, (301, 302))
        self.assertEqual(1, BlogPost.objects.count())
        self.assertEqual('post title', BlogPost.objects.get(id=2).title)

注:测试时settings.py 中关闭一下时区,USE_TZ = False,否则报错:

Creating test database for alias 'default'...
..E:\Envs\djangowebdev\lib\site-packages\django\db\models\fields\__init__.py:1430: RuntimeWarning: DateTimeField BlogPost.timestamp received a naive datetime (2018-01-05 21:04:12.141000) while time zone support is active.
  RuntimeWarning)
.E:\Envs\djangowebdev\lib\site-packages\django\db\models\fields\__init__.py:1430: RuntimeWarning: DateTimeField BlogPost.timestamp received a naive datetime (2018-01-05 21:04:12.256000) while time zone support is active.
  RuntimeWarning)
EF
运行测试

python manage.py test

测试成功:

Creating test database for alias 'default'...
.....
----------------------------------------------------------------------
Ran 5 tests in 0.556s

OK
Destroying test database for alias 'default'...
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值