Django simple sample
来源:互联网 发布:施工网络进度计划 编辑:程序博客网 时间:2024/05/24 05:29
我想写[Django实战]这系列的文章是因为我最近在开发一个数据库脚本发布系统,该系统只限于公司内部使用,它的功能非常简单明了:开发人员通过该系统提交SQL语句,DBA审核后执行,并将结果反馈给开发人员。
前两篇讲述了Django的理论,从这篇开始,我们真正进入Django实战部分,今天先从用户认证开始。
当大家平时打开一个网站时,第一步一般做什么?我猜大部分是先登录吧,所以我们就从用户认证开始。
打开用户认证
Django本身已经提供了用户认证模块,所以我们要做的事很简单,就是在它的基础上添加一些定制化的东西。默认情况下,Django的用户认证模块是打开的,可以通过以下步骤确认用户模块是否打开(在settings.py文件里):
1、确保 MIDDLEWARE_CLASSES 中包含 'django.contrib.sessions.middleware.SessionMiddleware'。
2、确认 INSTALLED_APPS 中有 'django.contrib.sessions'
3、将 'django.contrib.auth' 放在你的 INSTALLED_APPS 设置中,然后运行 manage.py syncdb以创建对应的数据库表。
4、确认 SessionMiddleware 后面的 MIDDLEWARE_CLASSES 设置中包含 'django.contrib.auth.middleware.AuthenticationMiddleware'。
数据库配置
用户认证系统必然离不开数据库,因为用户信息需要保存在数据库里,Django自带的用户认证系统也不例外。在使用它之前,必须配置数据库,Django支持大部分的主流数据库,这里我采用的是Oracle数据库,首先需要安装cx_Oracle模块,Django必须通过它才能访问Oracle数据库。至于如何安装cx_Oracle模块,这里就不讲了,具体查看官方文档。
接着在Oracle中创建一个用户,我们Django项目创建的所有表都建在该用户下,因此需要相应的权限:
SQL> create user dbrelease identified by * default tablespace dbrelease;SQL> grant resource,create session,unlimited tablespace to dbrelease;然后在settings.py中的Databases属性里设置django连接oracle:
DATABASES = { 'default': { 'ENGINE': 'django.db.backends.oracle', 'NAME': 'lxdbtest', 'USER': 'dbrelease', 'PASSWORD': '*', 'HOST': '192.168.1.16', 'PORT': '1521', }}注意:上面的NAME是指Oracle的instance_name
好了,下面验证是否可以成功连接Oracle:
进入Django项目的主目录,运行python manage.py shell进入交互命令行,然后输入:
>>> from django.db import connection>>> cursor = connection.cursor()如果没有报错,说明已经配置成功。
最后执行syncdb语句,从以下输出中我们可以发现,用户认证系统默认在数据库里创建了以下表:
# python manage.py syncdbCreating tables ...Creating table auth_permissionCreating table auth_group_permissionsCreating table auth_groupCreating table auth_user_groupsCreating table auth_user_user_permissionsCreating table auth_userCreating table django_content_typeCreating table django_sessionCreating table django_site
上一篇中,我们已经打开了Django自带的用户认证模块,并配置了数据库连接,创建了相应的表,本篇我们将在Django自带的用户认证的基础上,实现自己个性化的用户登录和注销模块。
首先,我们自己定义一个用户登录表单(forms.py):
from django import formsfrom django.contrib.auth.models import Userfrom bootstrap_toolkit.widgets import BootstrapDateInput, BootstrapTextInput, BootstrapUneditableInputclass LoginForm(forms.Form): username = forms.CharField( required=True, label=u"用户名", error_messages={'required': '请输入用户名'}, widget=forms.TextInput( attrs={ 'placeholder':u"用户名", } ), ) password = forms.CharField( required=True, label=u"密码", error_messages={'required': u'请输入密码'}, widget=forms.PasswordInput( attrs={ 'placeholder':u"密码", } ), ) def clean(self): if not self.is_valid(): raise forms.ValidationError(u"用户名和密码为必填项") else: cleaned_data = super(LoginForm, self).clean()我们定义的用户登录表单有两个域username和password,这两个域都为必填项。
接下来,我们定义用户登录视图(views.py),在该视图里实例化之前定义的用户登录表单
from django.shortcuts import render_to_response,render,get_object_or_404 from django.http import HttpResponse, HttpResponseRedirect from django.contrib.auth.models import User from django.contrib import authfrom django.contrib import messagesfrom django.template.context import RequestContextfrom django.forms.formsets import formset_factoryfrom django.core.paginator import Paginator, PageNotAnInteger, EmptyPagefrom bootstrap_toolkit.widgets import BootstrapUneditableInputfrom django.contrib.auth.decorators import login_requiredfrom .forms import LoginFormdef login(request): if request.method == 'GET': form = LoginForm() return render_to_response('login.html', RequestContext(request, {'form': form,})) else: form = LoginForm(request.POST) if form.is_valid(): username = request.POST.get('username', '') password = request.POST.get('password', '') user = auth.authenticate(username=username, password=password) if user is not None and user.is_active: auth.login(request, user) return render_to_response('index.html', RequestContext(request)) else: return render_to_response('login.html', RequestContext(request, {'form': form,'password_is_wrong':True})) else: return render_to_response('login.html', RequestContext(request, {'form': form,}))
该视图实例化了之前定义的LoginForm,它的主要业务逻辑是:
1. 判断必填项用户名和密码是否为空,如果为空,提示"用户名和密码为必填项”的错误信息
2. 判断用户名和密码是否正确,如果错误,提示“用户名或密码错误"的错误信息
3. 登陆成功后,进入主页(index.html)
其中,登录页面的模板(login.html)定义如下:
<!DOCTYPE html>{% load bootstrap_toolkit %}{% load url from future %}<html lang="en"><head> <meta charset="utf-8"> <title>数据库脚本发布系统</title> <meta name="description" content=""> <meta name="author" content="朱显杰"> {% bootstrap_stylesheet_tag %} {% bootstrap_stylesheet_tag "responsive" %} <style type="text/css"> body { padding-top: 60px; } </style> <!--[if lt IE 9]> <script src="//html5shim.googlecode.com/svn/trunk/html5.js"></script> <![endif]--> <script src="//ajax.googleapis.com/ajax/libs/jquery/1.9.0/jquery.min.js"></script> {% bootstrap_javascript_tag %} {% block extra_head %}{% endblock %}</head><body> {% if password_is_wrong %} <div class="alert alert-error"> <button type="button" class="close" data-dismiss="alert">×</button> <h4>错误!</h4>用户名或密码错误 </div> {% endif %} <div class="well"> <h1>数据库脚本发布系统</h1> <p> </p> <form class="form-horizontal" action="" method="post"> {% csrf_token %} {{ form|as_bootstrap:"horizontal" }} <p class="form-actions"> <input type="submit" value="登录" class="btn btn-primary"> <a href="/contactme/"><input type="button" value="忘记密码" class="btn btn-danger"></a> <a href="/contactme/"><input type="button" value="新员工?" class="btn btn-success"></a> </p> </form> </div></body></html>
最后还需要在urls.py里添加:
(r'^accounts/login/$', 'dbrelease_app.views.login'),
最终的效果如下:
1)当在浏览器里输入http://192.168.1.16:8000/accounts/login/,出现如下登陆界面:
2)当用户名或密码为空时,提示”用户名和密码为必填项",如下所示:
3)当用户名或密码错误时,提示“用户名或密码错误",如下所示:
4)如果用户名和密码都正确,进入主页(index.html)。
既然有login,当然要有logout,logout比较简单,直接调用Django自带用户认证系统的logout,然后返回登录界面,具体如下(views.py):
@login_requireddef logout(request): auth.logout(request) return HttpResponseRedirect("/accounts/login/")
上面@login[email protected]�图,否则将自动重定向至登录页面。
urls.py里添加:
(r'^accounts/logout/$', 'dbrelease_app.views.logout'),
前面我们实现了用户认证模块,在该模块里其实已经涉及到模块(ORM),但由于是Django自带的,大部分它都已经帮我们处理好,对于我们来说是透明的,本篇,我们将自己定义模型。
在Web开发中,我习惯从数据库层面开始,一方面是因为我本身是做DBA的,对数据库比较了解;另一部分也是因为相比于模板和视图来说,模型从设计之初基本已确定,不会有大的改动。
我们的模型models.py定义如下:
from django.db import modelsfrom django.contrib.auth.models import Userclass Manager(models.Model): id = models.AutoField(primary_key=True) username = models.CharField(max_length=30) first_name = models.CharField(max_length=30) last_name = models.CharField(max_length=30) email = models.EmailField(max_length=70) def __unicode__(self): return self.last_name + self.first_nameclass Dba(models.Model): id = models.AutoField(primary_key=True) username = models.CharField(max_length=30) first_name = models.CharField(max_length=30) last_name = models.CharField(max_length=30) email = models.EmailField(max_length=70) def __unicode__(self): return self.last_name + self.first_nameclass State(models.Model): id = models.AutoField(primary_key=True) statename = models.CharField(max_length=20) def __unicode__(self): return self.statenameclass Database(models.Model): id = models.AutoField(primary_key=True) databasename = models.CharField(max_length=30) databaseip = models.CharField(max_length=30) def __unicode__(self): return self.databasename + ' - ' + self.databaseipclass Task(models.Model): id = models.AutoField(primary_key=True) creater = models.ForeignKey(User) manager = models.ForeignKey(Manager) dba = models.ForeignKey(Dba) state = models.ForeignKey(State) databases = models.ManyToManyField(Database) sql = models.CharField(max_length=2000,blank=True,null=True) desc = models.CharField(max_length=2000,blank=True, null=True) createdtime = models.DateTimeField() lastupdatedtime = models.DateTimeField(blank=True,null=True) dbacomment = models.CharField(max_length=2000,blank=True,null=True) attachment = models.FileField(upload_to='tasks',blank=True,null=True) def __unicode__(self): return str(self.id)
其中最核心的表是最后一张Task,在业务逻辑上代表开发人员提交给DBA的一个数据库更改请求,其它所有表都是围绕这个表创建的:Manager表是Task.manager的外键,Dba表是Task.dba的外键,State表是Task.state的外键,其中比较特殊的是Task.databases和Database表是多对多的关系。还有一点要注意的是,Task.creater是Django自带的用户表auth_user的外键。
以上models.py定义了ORM关系,但当前这些表只存在models.py中,在数据库中还不存在,我们需要通过以下步骤同步数据库:
首先,通过以下语句验证models.py定义模型的正确性:
python manage.py validate如果上面没有错误,就可以执行如下语句同步数据库了(在同步之前,一定要先确认settings.py中DATABASES属性已正确配置,具体看第3篇):
python manage.py syncdb如果你想知道syncdb究竟在数据库里做了什么,可以执行如下语句获得DDL:
python manage.py sqlall app_name至此,模型已经创建成功,之后我们就可以在Django中自由的操纵数据库了。
在上一篇中,我们自己定义了数据库模型(models.py),并已同步至数据库中,那么如何插入、更新、删除表中数据呢?方法有很多,比如直接写SQL语句在数据库层面插入或调用模型的API,但这两种方法都需要写代码实现,可不可以有更直观页面操作呢?答案当然是肯定的,这就是Django自带的Admin模块,本篇主要讲述它。
首先,我们需要通过以下步骤开启Admin模块:
第一步:对settings.py做如下修改:
1)保证INSTALLED_APPS中包含'django.contrib.auth','django.contrib.contenttypes'和'django.contrib.sessions'(因为我们之前已经使用了Django自动的用户认证系统,因此这三个包应该就在开启的状态)
2)在INSTALLED_APPS中把'django.contrib.admin'和'django.contrib.admindocs'的注释去掉
3)确保MIDDLEWARE_CLASSES 包含'django.middleware.common.CommonMiddleware' 、'django.contrib.sessions.middleware.SessionMiddleware' 和'django.contrib.auth.middleware.AuthenticationMiddleware'
第二步:运行 python manage.py syncdb 。这一步将生成管理界面使用的额外数据库表
第三步:将admin访问配置在URLconf(记住,在urls.py中). 默认情况下,命令django-admin.py startproject生成的文件urls.py是将Django admin的路径注释掉的,你所要做的就是取消注释。如下所示:
# Uncomment the next two lines to enable the admin:from django.contrib import adminadmin.autodiscover()urlpatterns = patterns('', # Examples: # url(r'^$', 'dbrelease.views.home', name='home'), # url(r'^dbrelease/', include('dbrelease.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)),...)
第四步:创建admin.py文件,内容如下:
from django.contrib import adminfrom .models import *admin.site.register(Manager)admin.site.register(Dba)admin.site.register(State)admin.site.register(Database)admin.site.register(Task)
当这一切都配置完毕之后,在浏览器中输入http://192.168.1.16:8000/admin/,登陆成功后就可以使用Admin管理工具了,界面如下:
从以上页面我们发现,除了我们自己定义的模型(Dbrelease_app下的表)外,还有我们之前讲过的Django自带的用户认证模块(Auth)和(Sites)。
1.创建一个项目
- django-admin.py startproject myweb
项目里有一下几个目录
- myweb/
- ├── manage.py #django自带的服务器管理
- └── myweb
- ├── __init__.py #表明这是一个包结构的,这是一个模块
- ├── settings.py #包含项目的所有配置参数
- ├── urls.py #URL根配置
- └── wsgi.py #内置runserver命令的WSGI应用配置
2.更改项目里的基本配置
settings.py
- vim myweb/myweb/settings.py
- TIME_ZONE = 'Asia/Shanghai' #设置时区
- LANGUAGE_CODE = 'zh-cn' #设置语言类型
- INSTALLED_APPS = (
- 'django.contrib.admin',
- 'django.contrib.auth',
- 'django.contrib.contenttypes',
- 'django.contrib.sessions',
- 'django.contrib.messages',
- 'django.contrib.staticfiles',
- 'blog', #增加一个自己的app
- )
urls.py
- vim myweb/myweb/urls.py
- from django.conf.urls import patterns, include, url
- from django.contrib import admin
- urlpatterns = patterns('',
- # Examples:
- # url(r'^$', 'myweb.views.home', name='home'),
- # url(r'^blog/', include('blog.urls')),
- url(r'^admin/', include(admin.site.urls)),
- url(r'^blog/index/$','blog.views.index'), #增加这句,表明访问blog/index的时候,调用blog中views里的index方法
- )
3.创建blog app
- cd myweb
- django-admin.py startapps blog #blog要与settings里面添加的blog要保持一致
blog的目录结构
- blog
- ├── admin.py
- ├── __init__.py
- ├── migrations
- │ └── __init__.py
- ├── models.py
- ├── tests.py
- └── views.py
4.访问实例
修改blog里的views.py
- vim blog/views.py
- from django.http import HttpResponse
- def index(req):
- return HttpResponse('<h1>hello</h1>')
5.运行manage.py
- python manage.py migrate #如果提示未迁移,则运行这个命令,会有提示
- python manage.py runserver
- django simple sample
- Django simple sample
- [Simple Factory]:Source Sample
- a simple jsm sample
- Simple Windows Service Sample
- Simple Windows Service Sample
- A simple Hibernate sample
- A simple mysql sample
- C++ simple sample IOCP
- Indexing Service simple sample
- Sql Sample(simple)
- JAX-RS Simple SSE Sample
- django初体验-网站sample
- A Simple Sample for Expression Tree
- A Simple Sample for Expression Tree
- A simple sample show generic interface usage
- Using orientation sensors: Simple Compass sample
- pyvisa 1.4 & 1.6 -simple sample
- synchronized的使用方法(2)
- JDK安装与环境变量配置
- poj 3278 bfs
- ArcEngine定义查询
- bzoj3667: Rabin-Miller算法
- Django simple sample
- 初始化块
- Android开发命名规范和编码规范
- JdbcTemplate下访问Oracle数据库插入数据时返回序列增长的主键
- C/S和B/S两种架构区别
- PHP数据库操作类
- 熊猫阿波的故事
- 大数相乘(java)
- 安全模式下的加解密