这篇博客摘自《Python 核心编程》(第三版)
pip install Django==1.10.8
在 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
INSTALLED_APPS = [
...
'blog',
]
LANGUAGE_CODE = 'zh-Hans'
TIME_ZONE = 'Asia/Shanghai'
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': 'testdb',
'USER': 'root',
'PASSWORD': '123456',
'HOST': 'localhost',
'PORT': '3306',
}
}
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
在 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),
]
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
python manage.py runserver 8080
访问:http://localhost:8080/admin
填写创建的超级用户名和密码,登录后看到 admin 主页
尝试添加 BlogPost 数据
点击 BLOG / Blog posts,可以看到目前的数据
新的 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)
更改后的页面
# 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
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Blogtitle>
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/
# 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',)
# 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
...
<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()
# 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 中
# 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
...
...
# 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'...