1.1.创建项目和app
django-admin startproject mysite_login
python manage.py startapp login
-admin startproject mysite_login
python manage.py startapp login
1.2.设置时区和语言
Django默认使用美国时间和英语,在项目的settings文件中,如下所示:
LANGUAGE_CODE = 'en-us'
TIME_ZONE = 'UTC'
USE_I18N = True
USE_L10N = True
USE_TZ = True
= 'en-us'
TIME_ZONE = 'UTC'
USE_I18N = True
USE_L10N = True
USE_TZ = True
我们把它改为亚洲/上海
时间和中文
LANGUAGE_CODE = 'zh-hans'
TIME_ZONE = 'Asia/Shanghai'
USE_I18N = True
USE_L10N = True
USE_TZ = False
= 'zh-hans'
TIME_ZONE = 'Asia/Shanghai'
USE_I18N = True
USE_L10N = True
USE_TZ = False
1.3.启动
运行测试一下工程,在本机的浏览器中访问http://127.0.0.1:8000/
二、设计数据模型
2.1.数据库模型设计
作为一个用户登录和注册项目,需要保存的都是各种用户的相关信息。很显然,我们至少需要一张用户表User,在用户表里需要保存下面的信息:
- 用户名
- 密码
- 邮箱地址
- 性别
- 创建时间
进入login/models.py,代码如下
# login/models.py
from django.db import models
class User(models.Model):
'''用户表'''
gender = (
('male','男'),
('female','女'),
)
name = models.CharField(max_length=128,unique=True)
password = models.CharField(max_length=256)
email = models.EmailField(unique=True)
sex = models.CharField(max_length=32,choices=gender,default='男')
c_time = models.DateTimeField(auto_now_add=True)
def __str__(self):
return self.name
class Meta:
ordering = ['c_time']
verbose_name = '用户'
verbose_name_plural = '用户'
/models.py
from django.db import models
class User(models.Model):
'''用户表'''
gender = (
('male','男'),
('female','女'),
)
name = models.CharField(max_length=128,unique=True)
password = models.CharField(max_length=256)
email = models.EmailField(unique=True)
sex = models.CharField(max_length=32,choices=gender,default='男')
c_time = models.DateTimeField(auto_now_add=True)
def __str__(self):
return self.name
class Meta:
ordering = ['c_time']
verbose_name = '用户'
verbose_name_plural = '用户'
各字段含义:
- name必填,最长不超过128个字符,并且唯一,也就是不能有相同姓名;
- password必填,最长不超过256个字符(实际可能不需要这么长);
- email使用Django内置的邮箱类型,并且唯一;
- 性别使用了一个choice,只能选择男或者女,默认为男;
- 使用
__str__
帮助人性化显示对象信息; - 元数据里定义用户按创建时间的反序排列,也就是最近的最先显示;
注意:这里的用户名指的是网络上注册的用户名,不要等同于现实中的真实姓名,所以采用了唯一机制。如果是现实中可以重复的人名,那肯定是不能设置unique的。
2.2.设置数据库为Mysql
在settings.py修改
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': 'django', #数据库名字
'USER': 'root', #账号
'PASSWORD': '123456', #密码
'HOST': '127.0.0.1', #IP
'PORT': '3306', #端口
}
}
= {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': 'django', #数据库名字
'USER': 'root', #账号
'PASSWORD': '123456', #密码
'HOST': '127.0.0.1', #IP
'PORT': '3306', #端口
}
}
init.py里面导入pymysql模块
# login/init.py
import pymysql
pymysql.install_as_MySQLdb()
/init.py
import pymysql
pymysql.install_as_MySQLdb()
2.3.数据库迁移
注册app
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'login',
]
= [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'login',
]
迁移到数据库
python manage.py makemigrations
python manage.py migrate
.py makemigrations
python manage.py migrate
三、admin后台
3.1.在admin中注册模型
# login/admin.py
from django.contrib import admin
from . import models
admin.site.register(models.User)
/admin.py
from django.contrib import admin
from . import models
admin.site.register(models.User)
3.2.创建超级管理员
python manage.py createsuperuser
.py createsuperuser
然后再增加几个测试用户
四、url路由和视图
前面我们已经创建好数据模型了,并且在admin后台中添加了一些测试用户。下面我们就要设计好站点的url路由、对应的处理视图函数以及使用的前端模板了。
4.1.路由设计
初步设想需要下面的四个URL:
考虑到登录系统属于站点的一级功能,为了直观和更易于接受,这里没有采用二级路由的方式,而是在根路由下直接编写路由条目,同样也没有使用反向解析名(name参数)。
# mysite_login/urls.py
from django.conf.urls import url
from django.contrib import admin
from login import views
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^index/', views.index),
url(r'^login/', views.login),
url(r'^register/', views.register),
url(r'^logout/', views.logout),
]
/urls.py
from django.conf.urls import url
from django.contrib import admin
from login import views
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^index/', views.index),
url(r'^login/', views.login),
url(r'^register/', views.register),
url(r'^logout/', views.logout),
]
4.2.架构初步视图
路由写好了,就进入login/views.py
文件编写视图的框架,代码如下:
# login/views.py
from django.shortcuts import render,redirect
def index(request):
pass
return render(request,'login/index.html')
def login(request):
pass
return render(request,'login/login.html')
def register(request):
pass
return render(request,'login/register.html')
def logout(request):
pass
return redirect('/index/')
/views.py
from django.shortcuts import render,redirect
def index(request):
pass
return render(request,'login/index.html')
def login(request):
pass
return render(request,'login/login.html')
def register(request):
pass
return render(request,'login/register.html')
def logout(request):
pass
return redirect('/index/')
我们先不着急完成视图内部的具体细节,而是把框架先搭建起来。
4.3.创建HTML页面文件
在项目根路径的login目录中创建一个templates目录,再在templates目录里创建一个login目录
在login/templates/login
目录中创建三个文件index.html
、login.html
以及register.html
,并写入如下的代码:
index.html
{
#login/templates/login/index.html#}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>首页</title>
</head>
<body>
<h1>首页</h1>
</body>
</html>
#login/templates/login/index.html#}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>首页</title>
</head>
<body>
<h1>首页</h1>
</body>
</html>
login.html
{
#login/templates/login/login.html#}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>登录</title>
</head>
<body>
<h1>登录页面</h1>
</body>
</html>
#login/templates/login/login.html#}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>登录</title>
</head>
<body>
<h1>登录页面</h1>
</body>
</html>
register.html
{
#login/templates/login/register.html#}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>注册</title>
</head>
<body>
<h1>注册页面</h1>
</body>
</html>
#login/templates/login/register.html#}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>注册</title>
</head>
<body>
<h1>注册页面</h1>
</body>
</html>
五、前端页面设计
5.1.原生HTML页面
login.html
文件中的内容,写入下面的代码:
{
#login/templates/login/login.html#}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>登录</title>
</head>
<body>
<div style="margin: 15% 40%;">
<h1>欢迎登录!</h1>
<form action="/login/" method="post">
<p>
<label for="id_username">用户名:</label>
<input type="text" id="id_username" name="username" placeholder="用户名" autofocus required />
</p>
<p>
<label for="id_password">密码:</label>
<input type="password" id="id_password" placeholder="密码" name="password" required >
</p>
<input type="submit" value="确定">
</form>
</div>
</body>
</html>
#login/templates/login/login.html#}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>登录</title>
</head>
<body>
<div style="margin: 15% 40%;">
<h1>欢迎登录!</h1>
<form action="/login/" method="post">
<p>
<label for="id_username">用户名:</label>
<input type="text" id="id_username" name="username" placeholder="用户名" autofocus required />
</p>
<p>
<label for="id_password">密码:</label>
<input type="password" id="id_password" placeholder="密码" name="password" required >
</p>
<input type="submit" value="确定">
</form>
</div>
</body>
</html>
可以看到如下图的页面:
5.2.引入Bootstrap
根目录下新建一个static目录,并将解压后的bootstrap-3.3.7-dist
目录,整体拷贝到static目录中,如下图所示:
由于Bootstrap依赖JQuery,所以我们需要提前下载并引入JQuery:
下载地址
在static目录下,新建一个css和js目录,作为以后的样式文件和js文件的存放地,将我们的jquery文件拷贝到static/js
目录下。
然后打开项目的settings文件,在最下面添加配置,用于指定静态文件的搜索目录:
STATIC_URL = '/static/'
STATICFILES_DIRS = [
os.path.join(BASE_DIR, "static"),
]
= '/static/'
STATICFILES_DIRS = [
os.path.join(BASE_DIR, "static"),
]
5.3.创建base.html模板
既然要将前端页面做得像个样子,那么就不能和前面一样,每个页面都各写各的,单打独斗。一个网站有自己的统一风格和公用部分,可以把这部分内容集中到一个基础模板base.html
中。现在,在根目录下的templates中新建一个base.html
文件用作站点的基础模板。
在Bootstrap文档中,为我们提供了一个非常简单而又实用的基本模板,代码如下:
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<!-- 上述3个meta标签*必须*放在最前面,任何其他内容都*必须*跟随其后! -->
<title>Bootstrap 101 Template</title>
<!-- Bootstrap -->
<link href="css/bootstrap.min.css" rel="stylesheet">
<!-- HTML5 shim and Respond.js for IE8 support of HTML5 elements and media queries -->
<!-- WARNING: Respond.js doesn't work if you view the page via file:// -->
<!--[if lt IE 9]>
<script src="https://cdn.bootcss.com/html5shiv/3.7.3/html5shiv.min.js"></script>
<script src="https://cdn.bootcss.com/respond.js/1.4.2/respond.min.js"></script>
<![endif]-->
</head>
<body>
<h1>你好,世界!</h1>
<!-- jQuery (necessary for Bootstrap's JavaScript plugins) -->
<script src="https://cdn.bootcss.com/jquery/1.12.4/jquery.min.js"></script>
<!-- Include all compiled plugins (below), or include individual files as needed -->
<script src="js/bootstrap.min.js"></script>
</body>
</html>
!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<!-- 上述3个meta标签*必须*放在最前面,任何其他内容都*必须*跟随其后! -->
<title>Bootstrap 101 Template</title>
<!-- Bootstrap -->
<link href="css/bootstrap.min.css" rel="stylesheet">
<!-- HTML5 shim and Respond.js for IE8 support of HTML5 elements and media queries -->
<!-- WARNING: Respond.js doesn't work if you view the page via file:// -->
<!--[if lt IE 9]>
<script src="https://cdn.bootcss.com/html5shiv/3.7.3/html5shiv.min.js"></script>
<script src="https://cdn.bootcss.com/respond.js/1.4.2/respond.min.js"></script>
<![endif]-->
</head>
<body>
<h1>你好,世界!</h1>
<!-- jQuery (necessary for Bootstrap's JavaScript plugins) -->
<script src="https://cdn.bootcss.com/jquery/1.12.4/jquery.min.js"></script>
<!-- Include all compiled plugins (below), or include individual files as needed -->
<script src="js/bootstrap.min.js"></script>
</body>
</html>
将它整体拷贝到base.html
文件中。
5.4.创建页面导航条
Bootstrap提供了现成的导航条组件
<nav class="navbar navbar-default">
<div class="container-fluid">
<!-- Brand and toggle get grouped for better mobile display -->
<div class="navbar-header">
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#bs-example-navbar-collapse-1" aria-expanded="false">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="#">Brand</a>
</div>
<!-- Collect the nav links, forms, and other content for toggling -->
<div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
<ul class="nav navbar-nav">
<li class="active"><a href="#">Link <span class="sr-only">(current)</span></a></li>
<li><a href="#">Link</a></li>
<li class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">Dropdown <span class="caret"></span></a>
<ul class="dropdown-menu">
<li><a href="#">Action</a></li>
<li><a href="#">Another action</a></li>
<li><a href="#">Something else here</a></li>
<li role="separator" class="divider"></li>
<li><a href="#">Separated link</a></li>
<li role="separator" class="divider"></li>
<li><a href="#">One more separated link</a></li>
</ul>
</li>
</ul>
<form class="navbar-form navbar-left">
<div class="form-group">
<input type="text" class="form-control" placeholder="Search">
</div>
<button type="submit" class="btn btn-default">Submit</button>
</form>
<ul class="nav navbar-nav navbar-right">
<li><a href="#">Link</a></li>
<li class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">Dropdown <span class="caret"></span></a>
<ul class="dropdown-menu">
<li><a href="#">Action</a></li>
<li><a href="#">Another action</a></li>
<li>