python Django 学习笔记(六)—— 写一个简单blog做增删改练手
简单效果图
1,创建一个项目myblog 可参考这里
myblog/ manage.py myblog/ __init__.py settings.py urls.py wsgi.py
2,创建blogs app 可参考这里
myblog/myblog/blogs/ __init__.py models.py tests.py views.py
- 编写models.py
#vim: set fileencoding=utf-8: from django.db import models # Create your models here. class Blog(models.Model): title = models.CharField(u'标题', max_length=50) author = models.CharField(u'作者', max_length=10) content = models.CharField(u'正文', max_length=2000) post_date = models.DateTimeField(u'发布时间',auto_now_add=True) class Meta: ordering = ['-post_date']
- 模型安装(修改settings.py)
import os.path #加载模版需要导入库 #数据库连接 DATABASES = { 'default': { 'ENGINE': 'django.db.backends.mysql', # Add 'postgresql_psycopg2', 'mysql', 'sqlite3' or 'oracle'. 'NAME': 'myblog', # Or path to database file if using sqlite3. # The following settings are not used with sqlite3: 'USER': 'root', 'PASSWORD': 'root', 'HOST': '127.0.0.1', # Empty for localhost through domain sockets or '127.0.0.1' for localhost through TCP. 'PORT': '3306', # Set to empty string for default. } } #模型安装 INSTALLED_APPS = ( 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.sites', 'django.contrib.messages', 'django.contrib.staticfiles', # Uncomment the next line to enable the admin: 'django.contrib.admin', 'myblog.blogs', # Uncomment the next line to enable admin documentation: # 'django.contrib.admindocs', ) #加载模版 TEMPLATE_DIRS = ( # Put strings here, like "/home/html/django_templates" or "C:/www/django/templates". # Always use forward slashes, even on Windows. # Don't forget to use absolute paths, not relative paths. os.path.join(os.path.dirname(__file__), 'templates').replace('\\','/'), ) MIDDLEWARE_CLASSES = ( 'django.middleware.common.CommonMiddleware', 'django.contrib.sessions.middleware.SessionMiddleware', 'django.middleware.csrf.CsrfViewMiddleware', #csrf防御,post提交跨站请求伪造 'django.contrib.auth.middleware.AuthenticationMiddleware', 'django.contrib.messages.middleware.MessageMiddleware', # Uncomment the next line for simple clickjacking protection: # 'django.middleware.clickjacking.XFrameOptionsMiddleware', ) #settings.py基本修改就这些了
-
采用 python manage.py validate 检查模型的语法和逻辑是否正确。
没有错误则执行 python manage.py syncdb创建数据表。
3,编写forms.py
myblog/myblog/forms.py
#vim: set fileencoding=utf-8: from django import forms class BlogForm(forms.Form): title = forms.CharField(label='标题') author = forms.CharField(label='作者') content = forms.CharField(label='正文',widget=forms.Textarea)
4,编写views.py
myblog/myblog/views.py
#vim: set fileencoding=utf-8: from django.http import HttpResponseRedirect from django.shortcuts import render_to_response from myblog.blogs.models import Blog from myblog import forms from django.template import RequestContext def blog_list(request): blog_list = Blog.objects.all() return render_to_response('blog_list.html',{'blog_list':blog_list}) def blog_form(request): if request.method == 'POST': form = forms.BlogForm(request.POST) if form.is_valid(): data = form.cleaned_data if 'id' not in data: blog = Blog(title=data['title'],author=data['author'],content=data['content']) blog.save() else: blog = Blog.object.get(id=data.id) blog.title = data['title'] blog.author = data['author'] blog.content = data['content'] blog.save() return HttpResponseRedirect('/blog/list') else: form = forms.BlogForm() return render_to_response('blog_form.html',{'form':form},context_instance=RequestContext(request)) def blog_del(request): errors = [] if 'id' in request.GET: bid_ = request.GET['id'] Blog.objects.filter(id=bid_).delete() return HttpResponseRedirect('/blog/list') else: errors.append("参数异常请刷新后重试") return render_to_response('blog_list.html', {'errors': errors}) def blog_view(request): errors = [] if 'id' in request.GET: bid_ = request.GET['id'] blog = Blog.objects.get(id=bid_) return render_to_response('blog_view.html',{'blog':blog}) else: errors.append("参数异常请刷新后重试") return render_to_response("blog_list.hmtl",{'errors':errors}) def blog_edit(request): errors = [] if 'id' in request.GET: bid_ = request.GET['id'] blog = Blog.objects.get(id=bid_) form = forms.BlogForm( initial = {'id':blog.id,'title':blog.title,'author':blog.author,'content':blog.content} ) return render_to_response('blog_form.html',{'form':form},context_instance=RequestContext(request)) else: errors.append("参数异常请刷新后重试") return render_to_response("blog_list.html",{'errors':errors})
5,创建模版文件
myblog/myblog/templates/ blog_form.html blog_list.html blog_view.html #blog_form.html <html> <meta http-equiv="Content-type" content="text/html; charset=utf-8"> <title>博客编辑</title> <head></head> <body> {% if errors %} <ul> {% for error in errors %} <li style="color: red;">{{error}}</li> {% endfor %} </ul> {% endif %} <a href="/blog/list">返回主页>></a><p/> <form action="/blog/form" method="post"> {% csrf_token %} <table> {{ form.as_table }} </table> <input type="submit" value="保存"> </form> </body> </html> #blog_list.html <html> <meta http-equiv="Content-type" content="text/html; charset=utf-8"> <title>主页-博客列表</title> <head></head> <body> {% if errors %} <ul> {% for error in errors %} <li style="color: red;">{{error}}</li> {% endfor %} </ul> {% endif %} <a href="/blog/form">去写博客>></a><p/> <table cellpadding="0" cellpadding="0" width="100%" border="1" > <tr height="20"> <td>编号</td> <td>标题</td> <td>作者</td> <td>发布时间</td> <td>操作</td> </tr> {% for blog in blog_list %} <tr> <td>{{forloop.counter}}</td> <td><a href="/blog/view?id={{blog.id}}">{{blog.title}}</a></td> <td>{{blog.author}}</td> <td>{{blog.post_date | date:"Y-m-d H:i:s"}}</td> <td><a href="/blog/edit?id={{blog.id}}">修改</a> <a href="/blog/delete?id={{blog.id}}">删除</a></td> </tr> {% empty %} <tr><td colspan="4">还没有添加博客内容</td></tr> {% endfor %} </table> </body> </html> #blog_view.html <html> <meta http-equiv="Content-type" content="text/html; charset=utf-8"> <title>{{blog.title}}</title> <head></head> <body> {% if errors %} <ul> {% for error in errors %} <li style="color: red;">{{error}}</li> {% endfor %} </ul> {% endif %} <a href="/blog/list">返回主页>></a><p/> <h2>{{blog.title}}</h2> <p>作者:{{blog.author}} {{blog.post_date | date:'Y-m-d H:i:s'}}<p> <p>{{blog.content}}</p> </body> </html>
6,修改urls.py
from django.conf.urls import patterns, include, url from myblog import views # Uncomment the next two lines to enable the admin: # from django.contrib import admin # admin.autodiscover() urlpatterns = patterns('', # Examples: # url(r'^$', 'myblog.views.home', name='home'), # url(r'^myblog/', include('myblog.foo.urls')), # Uncomment the admin/doc line below to enable admin documentation: # url(r'^admin/doc/', include('django.contrib.admindocs.urls')), # Uncomment the next line to enable the admin: # url(r'^admin/', include(admin.site.urls)), url(r'^blog/list$', views.blog_list), url(r'^blog/form$', views.blog_form), url(r'^blog/delete$', views.blog_del), url(r'^blog/view$', views.blog_view), url(r'^blog/edit$', views.blog_edit), )
7,启动开发服务器 http://127.0.0.1:8000/blog/list
8,遇到的问题
1,CSRF verification failed. Request aborted.
Forbidden (403)
CSRF verification failed. Request aborted.
Help
Reason given for failure:
CSRF token missing or incorrect.
In general, this can occur when there is a genuine Cross Site Request Forgery, or when Django's CSRF mechanism has not been used correctly. For POST forms, you need to ensure:
Your browser is accepting cookies.
The view function uses RequestContext for the template, instead of Context.
In the template, there is a {% csrf_token %} template tag inside each POST form that targets an internal URL.
If you are not using CsrfViewMiddleware, then you must use csrf_protect on any views that use the csrf_token template tag, as well as those that accept the POST data.
You're seeing the help section of this page because you have DEBUG = True in your Django settings file. Change that to False, and only the initial error message will be displayed.
You can customize this page using the CSRF_FAILURE_VIEW setting.
解决方法:
- 在视图函数里用RequestContext类代替Context。RequestContext是Context的子类,具体可自行google。
- 在模版表单中插入 {% csrf_token%}
(本例子采用以上方法,可查看views.py 中blog_form()函数,和blog_form.html模版页面)
另外也可以注释掉settings.py
#'django.middleware.csrf.CsrfViewMiddleware', #csrf防御,post提交跨站请求伪造
2,还有个问题,就是在修改的时候怎么把对应id传入模版blog_form.html页面。暂未解决..