Django是基于Python的高级Web开发框架。本篇文章进行的是简单的功能的实现,后续会进行安全工具相应的开发。
下面只大致说下过程,具体的实现看源代码即可。
安装:
pip install Django==1.11.4
或直接到Github下载源代码安装
确认是否安装:python –m Django –version
创建新项目:
django-admin startproject djangotest
cd djangotest/
ls
项目目录结构如图:
manage.py:与项目进行交互的命令行工具集的入口,即项目管理器,可执行python manage.py来查看所有命令
启动服务:python manage.py runserver 8080
Django shell:python manage.py shell,自动引入项目环境,可以通过其与项目交互进行测试
djangotest目录为一个容器,包含项目的一些基本配置。
wsgi.py:Python Web Server Gateway Interface(Python服务器网关接口),即Python应用与Web服务器之间的接口。
urls.py:URL配置文件
settings.py:
BASE_DIR指定项目根目录。
SECRET_KEY即密钥,项目启动时需要用到。
DEBUG即调试,在测试时用。
ALLOWED_HOSTS即允许访问的主机名,当列表中包含localhost值时即只允许通过localhost的主机名进行访问。
INSTALLED_APPS即已安装的应用,若自己创建了新的应用则添加进去。
MIDDLEWARE即中间件,是Django自带的工具集。
ROOT_URLCONF即URL配置文件,指向urls.py文件。
TEMPLATES即模板,即关于模板的配置,模板简单地说即HTML文件。
WSGI_APPLICATION
DATABASES,数据库配置。
AUTH_PASSWORD_VALIDATORS和密码认证相关。
LANGUAGE_CODE语言编码,默认为en-us。
TIME_ZONE时区,默认为UTC。
USE_I18N
USE_L10N
USE_TZ
STATIC_URL
__init__.py:Python中声明模块的文件,默认内容为空。
创建应用:
新建blog应用:python manage.py startapp blog
接着将新建的应用添加到settings.py的INSTALLED_APPS中:
migrations:数据移植模块,内容自动生成
admin.py:应用的后台管理系统配置
apps.py:当前应用的配置,在Django-1.9后才自动生成
models.py:数据模块,使用ORM框架
tests.py:自动化测试模块,可再次编写测试脚本
views.py:执行响应的代码所在模块,是代码进行逻辑处理的地方,项目中大部分代码在此编写
编写views.py:
每个响应对应一个函数,因而每个函数必须返回一个响应。
函数必须有一个参数,一般约定为request。
每一个响应或函数对应一个URL。
添加内容到urls.py文件:
启动服务:python manage.py runserver 1234
访问相应的目录:
第二种配置url的方法,如注释所说:
直接修改相应的部分:
然后在blog目录下新建urls.py文件:
注意:url函数中的目录名后要添加/,否则容易出错。
再度访问:
Templates模板:
HTML文件,使用Django模板语言(Django Template Language,DTL),也可以使用第三方模板
开发模板的步骤:
1、在根目录下创建Templates目录
2、在该目录下创建HTML文件
3、在views.py中返回render()
访问:
注意点:Django会按照INSTALLED_APPS中的添加顺序来查找Templates。
解决Templates冲突的方法:在Templates目录下创建以APP名为名称的目录并将HTML文件放入新创建的目录中。
另一种创建templates目录是创建在项目的根目录中而不是在应用的目录中,然后再在该目录下创建和应用名一样的目录,再在其中创建html文件即可,注意一点的是,此时因为是创建在项目根目录中,需要在settings.py文件中设置:
Models:
通常一个Model对应数据库的一张表,是以类的形式表现出来的。
示例的models.py文件:
创建步骤:
1、在根目录下创建models.py,并引入models模块
2、创建类,继承models.Model,该类即是一张数据表
3、在类中创建字段
生成数据表:
python manage.py makemigrations app名(可选)
python manage.py migrate
查看:
在根目录的migrations目录中生成移植文件:
可以看到id字段是自动生成的主键,因为在初始创建字段时并没有指定主键。
查看SQL语句:python manage.py sqlmigrate 应用名 文件id
这里使用的是默认的sqlite3数据库,其在根目录中保存为db.sqlite3,查看其需要特定的软件,这里就不下载安装了:
页面呈现数据:
后台修改views.py,添加数据保存到数据库并从数据库读取数据返回到前端:
注意,这里添加id=10的参数是为了每次调用都是进行相同的内容进行替换保存,以避免每调用一次就新增一项数据。
前端修改index.html:
模板直接使用对象以及对象的“.”操作,如{{ article.title }}
最后访问页面即可:
Admin:
Django自带的自动化数据管理界面,被授权的用户可直接在admin中管理数据库。
配置admin:
创建超级用户:python manage.py createsuperuser
可以将页面的英文修改为中文,到settings.py的LANGUAGE_CODE默认的‘en-us’改为‘zh-hans’即可:
配置应用:
在admin.py中引入自身的models模块
编辑admin.py:
刷新页面:
修改数据:
再访问:
修改数据默认名称:
接着在Article类下添加一个方法,根据Python版本,若为3以上版本则使用__str__(self)方法,若为2系列版本则使用__unicode__(self)方法,添加这个方法是为了在查询时实现相应的内容,这里是实现将显示的内容从对象改为文章标题:
再次查看:
改进:
在admin.py中添加ArticleAdmin类并通过list_display来设置文章列表显示页面中显示的列的内容:
完善Blog开发:
namespace与name参数的注意点:
1、写在include()的第二个参数位置,namespace=’blog’
先在djangotest/djangotest/urls.py的include()函数中添加namespace参数:
2、应用下则写在url()的第三个参数位置,name=’article_page’
然后到djangotest/blog/urls.py中的url()函数中添加name参数:
主要取决于是否使用include引用另一个url配置文件。
最后在HTML文件中:
template中超链接href可以用“{% url ‘app_name:url_name’ param %}”
app_name和url_name都在urls.py中配置
认证登录:
contrib模块:django.contrib.auth,默认的认证框架。
创建users:
1、示例代码如下:
from django.contrib.auth.models import User user = User.objects.create_user(‘admin’, ‘[email protected]’, ‘password’)
2、python manage.py createsuperuser
修改密码:
1、python manage.py changepassword username
2、示例代码如下:
from django.contrib.auth.models import User u = User.objects.get(username=’admin’) u.set_password(‘newpassword’) u.save()
认证Users:authenticate(username=’admin’, password=’password’),成功则返回User对象,否则返回None。
Web请求中的认证:request.user.is_authenticated()
登录用户:login(request, user),需要先进行认证
登出用户:logout(request)
只允许用户登录访问:
1、检查request.user.is_authenticated()
2、login_required装饰器
先创建一个member应用,在settings.py中添加应用名,然后创建forms.py:
主要是创建用户名和密码的表单类,其中Django用widget来定义数据项的格式,这里为密码格式的文本字段。
然后创建urls.py文件:
在views.py中编写用户登录的方法user_login()。
接着对之前blog应用的views.py中的方法调用login_required()方法进行装饰:
然后再在urls.py中配置一下url即可完成登录相关的功能。
代码实现:
这里重新新建项目来实现博客系统完整的搭建。
整个项目目录架构如下:
blog目录:
admin.py:
from django.contrib import admin from models import Article # Register your models here. class ArticleAdmin(admin.ModelAdmin): """docstring for ArticleAdmin""" list_display = ('title', 'content', 'pub_time') list_filter = ('pub_time',) admin.site.register(Article, ArticleAdmin)
models.py:
from __future__ import unicode_literals from django.db import models # Create your models here. class Article(models.Model): title = models.CharField(max_length=32, default='title') content = models.TextField(null=True) pub_time = models.DateTimeField(null=True) def __unicode__(self): return self.title
urls.py:
from django.conf.urls import url from . import views urlpatterns = [ url(r'^index/$', views.index, name='index'), url(r'^article/(?P<article_id>[0-9]+)$', views.article_page, name='article_page'), url(r'^edit/(?P<article_id>[0-9]+)$', views.edit_page, name='edit_page'), url(r'^change/$', views.change, name='change'), url(r'^delete/(?P<article_id>[0-9]+)$', views.delete_page, name='delete_page'), ]
views.py:
from django.shortcuts import render from django.http import HttpResponse from django.contrib.auth.decorators import login_required from . import models # Create your views here. @login_required def index(request): articles = models.Article.objects.all() return render(request, 'blog/index.html', {'articles':articles}) @login_required def article_page(request, article_id): article = models.Article.objects.get(pk=article_id) return render(request, 'blog/article_page.html', {'article':article}) @login_required def edit_page(request, article_id): if str(article_id) == '0': return render(request, 'blog/edit_page.html') article = models.Article.objects.get(pk=article_id) return render(request, 'blog/edit_page.html', {'article':article}) @login_required def change(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, 'blog/index.html', {'articles':articles}) article = models.Article.objects.get(pk=article_id) article.title = title article.content = content article.save() return render(request, 'blog/article_page.html', {'article':article}) @login_required def delete_page(request, article_id): models.Article.objects.filter(pk=article_id).delete() articles = models.Article.objects.all() return render(request, 'blog/index.html', {'articles':articles})
member目录:
forms.py:
from django import forms class LoginForm(forms.Form): username = forms.CharField() password = forms.CharField(widget=forms.PasswordInput)
urls.py:
from django.conf.urls import url from django.contrib.auth import views as auth_views from . import views urlpatterns = [ url(r'^$', views.user_login, name='login'), url(r'^logout-then-login/$', auth_views.logout_then_login, name='logout_then_login'), ]
views.py:
from __future__ import unicode_literals from django.shortcuts import render from django.http import HttpResponseRedirect from django.contrib.auth import authenticate, login from django.contrib import messages from .forms import LoginForm # Create your views here. def user_login(request): login_form = LoginForm() if request.method == 'POST': form = LoginForm(request.POST) if form.is_valid(): cd = form.cleaned_data user = authenticate(username=cd['username'], password=cd['password']) if user is not None: if user.is_active: login(request, user) return HttpResponseRedirect('/blog/index') else: messages.error(request, "Your username and password didn't match.") return HttpResponseRedirect('/') else: messages.error(request, "Your username and password didn't match.") return HttpResponseRedirect('/') else: return render(request, 'login/user_login.html', {'login_form':login_form})
myBlog目录:
urls.py:
from django.conf.urls import url, include from django.contrib import admin urlpatterns = [ url(r'^admin/', admin.site.urls), url(r'^blog/', include('blog.urls', namespace='blog')), url(r'^', include('member.urls', namespace='member')), url(r'^accounts/login/', include('member.urls')), ]
settings.py中修改几个地方即可:
templates目录:
login目录:
user_login.html:
<!DOCTYPE html> <head> <meta charset="utf-8"/> <title>MyBlog</title> </head> <body class="login"> <h2>MyBlog——简单的博客系统</h2> <div> <form action="{% url 'member:login' %}" method="post"> <h3>Login to your account</h3> {% if messages %} <h5> {% for message in messages %} {{ message }} {% endfor %} </h5> {% endif %} <div> <label>Username</label> <div> <input type="text" autocomplete="off" placeholder="Username" name="username"/> </div> </div> <br/> <div > <label>Password</label> <div> <input type="password" autocomplete="off" placeholder="Password" name="password"/> </div> </div> <br/> {% csrf_token %} <div> <button type="submit"> Login </button> </div> </form> </div> <br> <div class="copyright"> 2017 © SKI12 </div> </body> </html>
blog目录:
index.html:
<!DOCTYPE html> <html> <head> <title>MyBlog</title> </head> <body> <h1>MyBlog</h1> <a href="{% url 'blog:edit_page' 0 %}">编写博客</a> <p>博客列表</p> {% for article in articles %} <a href="{% url 'blog:article_page' article.id %}">{{ article.title }}</a> <br/> {% endfor %} <br> <a href="{% url 'member:logout_then_login' %}">Logout</a> </body> </html>
article_page.html:
<!DOCTYPE html> <html> <head> <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 %}">Edit</a> <a href="{% url 'blog:delete_page' article.id %}">Delete</a> <a href="{% url 'blog:index'%}">Home</a> <a href="{% url 'member:logout_then_login' %}">Logout</a> </body> </html>
edit_page.html:
<!DOCTYPE html> <html> <head> <title>Edit Page</title> </head> <body> <form action="{% url 'blog:change' %}" 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> <br/> <div> <a href="{% url 'blog:index'%}">Home</a> <a href="{% url 'member:logout_then_login' %}">Logout</a> </div> </body> </html>
最终的超简版博客系统效果如图:
首先访问的时候需要登录:
登录成功后转到blog主页:
点击编写博客进入编辑页面:
点击博客文章查看博客:
简易的功能完成了,后面就进一步进行安全开发。