? ? ? ? 在编写网站时,首先要确定的是网站的功能,比如注册登录,数据收集等等,有了明确的目标,才能更好的达成目的。
PS E:\Django_Master> django-admin startproject Project1
PS E:\Django_Master> cd .\Project1\
PS E:\Django_Master\Project1> python .\manage.py startapp mysite
通过上图代码,我们可以得到一个基础的Django web 模板,大致如下图。
#Ps:我这里并没有用虚拟环境,个人不推荐这种做法。
笔记一:MVT模式(models-views-templates)
? ? ? ? ? ? ? ? M:models,主要负责与数据库的交互。//可以制定数据表的列名
? ? ? ? ? ? ? ? V:views,用于接收命令,再通过代码给予回应。
????????????????T:templates,字面意思,也就是网页的模板。自己创建的文件夹。
这里我们先做一个简单的数据模型用来存储用户数据
"""
mysite/models.py
"""
from django.db import models
class User(models.Model):
name = models.CharField(max_length=128, unique=True)
password = models.CharField(max_length=256)
email = models.EmailField()
phone = models.CharField(max_length=15)
sex = models.CharField(max_length=10, choices=(('male', '男'), ('female', '女')), default='女')
create_time = models.DateTimeField(auto_now=True)
def __str__(self):
return self.name
unique :唯一标识
其中性别这一行也可以写成:
Gender = (
('male', '男'),
('female', '女'),
)
sex = models.CharField(max_length=10, choices=Gender, default='女')
?#Ps:也就是多写了一个Gender,但代码看起来就简洁多了。
至此models算是配置好了,下一步是对setting文件的配置。
首先我们找到跟项目文件同名的文件夹,我这里是Project1。
? ? ? ? ? 可以看到settings.py,就是这个深蓝色背景的。Open~
? ????????接着找到里面的DATABASES,建议Ctrl+F5快速定位。
? ????????在Django中 默认的数据库是sqlite,我个人偏向于MySQL。
'ENGINE': 'django.db.backends.mysql',
'NAME': 'my_django_db',
'USER': 'root',
'PASSWORD': 'root',
'HOST': '127.0.0.1',
'PORT': '3306',
NAME:数据库名称;
USER:mysql的用户名
PASSWORD:mysql的密码
HOST:IP地址
PORT:端口号
? ? ? ? 既然我们已经打开了setting,那就顺便配置一下时区以及static的路径
LANGUAGE_CODE = 'zh-hans'
TIME_ZONE = 'Asia/Shanghai'
USE_I18N = True
USE_L10N = True
USE_TZ = False
STATIC_URL = '/static/'
STATICFILES_DIRS = [
os.path.join(BASE_DIR, "static"),
]
PROJECT_ROOT = os.path.dirname(__file__)
STATICFILES_DIRS = (os.path.join(PROJECT_ROOT, 'static'),)
以及注册我们创建的应用
INSTALLED_APPS = [
'mysite',
...
]
接下来是重点部分,//敲黑板//。
如果现在我们就直接去迁移数据库,那么就会报错(针对数据库设置为mysql的用户),如下。
遇到这个问题呢,我们要先pip install pymysql(适用python3)
然后找到我们创建的应用文件夹下的__init__.py
输入以下代码:
import pymysql
pymysql.install_as_MySQLdb()
再迁移数据库就OK了。
makemigrations :在你的应用中创建一个文件夹其中记录所有关于modes.py的改动
migrate:建表
这时候我们进入数据库就可以看到我们的表已经生成了:
3_建立视图,模板并通过urls关联
?我们现在要做的是一个登录系统,由登录、注册、主页三个部分组成。
第一步、
在应用文件夹中新建templates文件夹,在templates文件夹下建一个跟应用文件夹同名的文件夹,在其中新建5个HTML文件,分别是index(主页)、login(登录页)、register(注册页)、? ?layout(模板/框架),login_layout(登录样式)。
#Ps:mysite是我的应用名称
?第二步、
我们打开应用文件夹下的views.py
?往里面塞入以下语句。
"""
mysite/views.py
"""
from django.shortcuts import render
def index(request):
pass
return render(request,'mysite/index.html')
def login(request):
pass
return render(request,'mysite/login.html')
def register(request):
pass
return render(request,'mysite/register.html')
def logout(request):
pass
return render(request,'mysite/logout.html')
render的作用是传输数据到目标,也就是把数据传给第二个参数,对应的是templates下的文件夹以及子文件,第三个参数是要传输的数据,这里省略,后面会写。
pass的作用是占位符,也就是说:‘它没用,但写了好看’。
最后一步、
我们先找到项目同名文件夹(后面简称为根文件夹)下的urls.py,将它copy到应用文件夹中。
修改根文件夹中urls.py的内容:
"""
Project1/urls.py
"""
from django.contrib import admin
from django.urls import path, include
from mysite import views
urlpatterns = [
path('',views.index),
path('mysite/',include('mysite.urls',namespace='mysite')),
path('admin/', admin.site.urls),
]
以及应用文件夹中的urls.py:
"""
mysite/urls.py
"""
from django.contrib import admin
from django.urls import path, include
from . import views
app_name = 'mysite'
urlpatterns = [
path('', views.index,name='home'),
path('login/', views.login,name='login'),
path('register/', views.register,name='register'),
path('logout/', views.logout,name='logout'),
path('admin/', admin.site.urls),
]
#Ps:注意,这两个urls中的mysite均为应用文件夹
完成以上步骤后我们就可以启动网站了。
在powershell 或者 cmd 或者其他shell中输入 python manage.py runserver
?可以看到,网站启动成功。在浏览器中输入网址即可打开页面。
?当然,因为我们什么都没做,所以页面中空空如也。
?4_登入系统的制作
前面的部分都是在打基础,现在开始才算是正文。
首先,我们在应用文件夹中创建一个forms.py文件,我们要通过这个文件来实现登入以及注册的数据传递。
forms.py文件的写法类似于models.py:
"""
mysite/forms.py
"""
from django import forms
#-----------------------------------------------
#login_form
#-----------------------
class UserForm(forms.Form):
username = forms.CharField(label="UserName", max_length=128, widget=forms.TextInput(attrs={'class': 'form-control'}))#attrs 这里是样式定义
password = forms.CharField(label="PassWord", max_length=256, widget=forms.PasswordInput(attrs={'class': 'form-control'}))
#-----------------------------------------------
#register_form
#-----------------------
class RegisterForm(forms.Form):
gender = (
('male', "男"),
('female', "女"),
)
username = forms.CharField(label="UserName", max_length=128, widget=forms.TextInput(attrs={'class': 'form-control'})) # attrs 这里是样式定义
password1 = forms.CharField(label="PassWord", max_length=256, widget=forms.PasswordInput(attrs={'class': 'form-control'}))
password2 = forms.CharField(label="Confirm PassWord", max_length=256, widget=forms.PasswordInput(attrs={'class': 'form-control'}))
phone = forms.CharField(label="Your phone",max_length=15)
email = forms.EmailField(label="E-mail", widget=forms.EmailInput(attrs={'class': 'form-control'}))
sex = forms.ChoiceField(label='sex', choices=gender)
之后我们开始操刀views.py:
首先是登录模块
"""
mysite/views.py
"""
#-----------------------------------------------
#login
#-----------------------
def login(request):
if request.session.get('is_authenticated',None):
return redirect('/mysite')
if request.method=='POST':
login_form=UserForm(request.POST)
if login_form.is_valid():
username=login_form.cleaned_data['username']
password=login_form.cleaned_data['password']
try:
user=models.User.objects.get(name=username)
if user.password==password:
request.session['is_authenticated']=True
request.session['user_name']=username
return redirect('/mysite')
else:
msg='密码错误'
except:
msg='用户不存在'
return render(request, 'mysite/login.html', locals())
login_form=UserForm()
return render(request, 'mysite/login.html', locals())
在登录函数中,我们的逻辑是:
1、先判断用户是否已经登入,如果已经登录了,那就不允许再登录,点击按钮会重定向到主页。
2、通过网页传参数的方式以采用不同的数据读取方式,这里因为前后端都是自己操作,所以直接写POST来对应网页内的method=POST就好了。
3、通过forms.py中的函数来获取网页内输入的数据。其中is_valid()是form自带的校验方法,对我这样的小白来说非常好用。
? ? ? ? cleaned_data:获取指定属性的值
4、当数据校验完毕且没有异常值之后,我们通过models.User.objects.get(name=username)
来获取数据库中的数据,这句代码翻译一手大致意思如下:
????????models:models.py
????????User:models.py中的class类
????????objects:类似于接口,用于数据库与模型的交互
????????get:返回数据库中满足条件的那一行数据。#Ps:极其挑剔,当获取的数据不存在或者存在多条数据时都会报错
????????name:models.py中的User类里面的一个属性
????????username:通过form传进来的参数,也就是网页中输入的参数之一
因为get方法只容许有一条数据,且我们之前在设计数据表时将name的unique设为True,也就是唯一性,所以当我们使用
user=models.User.objects.get(name=username)
语句时,如果数据库中没有数据,那么会报错,所以这里用try....except,当报错时,生成一个msg来展示报错原因,没有报错,那就进行下一步操作。
5、get没报错,说明用户存在,那么最后比较一下密码即可,密码正确,则重定向到主页,同时我们使用session这个中间件来存储登录信息,与第一步相呼应。
?然后是注册函数:
"""
mysite/views.py
"""
# -----------------------------------------------
# register
# -----------------------
def register(request):
if request.session.get('is_authenticated',None):
redirect('/mysite')
if request.method == 'POST':
register_form = RegisterForm(request.POST)
if register_form.is_valid():
username = register_form.cleaned_data['username']
password1 = register_form.cleaned_data['password1']
password2 = register_form.cleaned_data['password2']
phone = register_form.cleaned_data['phone']
email = register_form.cleaned_data['email']
sex = register_form.cleaned_data['sex']
if password1 != password2:
msg = '前后密码不一致'
return render(request, 'mysite/register.html', locals())
else:
if models.User.objects.filter(name=username):
msg = '该用户名已被使用'
return render(request, 'mysite/register.html', locals())
if models.User.objects.filter(email=email):
msg = '该邮箱已被使用'
return render(request, 'mysite/register.html', locals())
new_user = models.User.objects.create()
new_user.name = username
new_user.password = password1
new_user.phone = phone
new_user.email = email
new_user.sex = sex
new_user.save()
return redirect('/mysite/login')
return render(request, 'mysite/register.html', locals())
register_form = RegisterForm()
return render(request,'mysite/register.html',locals())
有了登录的思路在,注册也就简单了。
这里的
models.User.objects.create()
类似于在数据表中创建一行空着的数据,然后逐个的往里面添加参数就ok,最后用save()保存
最后是登出:
"""
mysite/views.py
"""
# -----------------------------------------------
# logout
# -----------------------
def logout(request):
if not request.session.get('is_authenticated',None):
return redirect('/mysite/login')
request.session.flush()
return redirect('/mysite')
登出函数首先判断是否登录,没登录就跳转到登录页面。
接着删除session中的数据,再跳转到主页。
5_登录系统的完成
MVT模式中的M:model、V:view我们已经完成了,现在我们开始编写T:templates下的文件 首先是主页:
<!--mysite/index.html-->
{% extends 'mysite/layout.html' %}
{% load static %}
{% block title %}主页{% endblock %}
{% block content %}
{% if request.session.is_authenticated %}
<h1>欢迎回来!{{ request.session.user_name }}</h1>
{% else %}
<h1>请登录</h1>
{% endif %}
{% endblock %}
首先,在主页的模板文件index.html中,我们使用了Django中的模板继承,也就是extend,它能使两个HTML页面融合到一块,且支持模块替换。
其次,我们通过对session中间件的is_authenticated属性进行判断,使其在面对不同情况时有对应的效果。
接下来是登录与注册页面login.html & register.html
<!----------------------------------------------------------------------------------->
<!--mysite/login.html-->
<!----------------------------------------------------------------------------------->
{% extends 'mysite/layout.html' %}
{% load static %}
{% block title %}登录{% endblock %}
{% block content %}
<form class='form-login' action="{% url 'mysite:login' %}" method="post">
{% csrf_token %}
<h2 class="text-center">欢迎登录</h2>
<div class="form-group">
{{ login_form.username.label_tag }}
{{ login_form.username}}
</div>
<div class="form-group">
{{ login_form.password.label_tag }}
{{ login_form.password }}
</div>
<a href="{% url 'mysite:register' %}"><input type="button" class="btn btn-default" value="没有账号?注册一个"></input></a>
<button type="submit" class="btn btn-primary pull-right form-group">Go!</button>
<br>
<br>
{% if msg %}
<div class="alert alert-warning">{{ msg }}</div>
{% endif %}
</form>
{% endblock %}
<!----------------------------------------------------------------------------------->
<!--mysite/register.html-->
<!----------------------------------------------------------------------------------->
{% extends 'mysite/layout.html' %}
{% block title %}注册{% endblock %}
{% block content %}
<div class="container">
<div class="col-md-4 col-md-offset-4" style="margin-top: 12%">
<form class='form-register' action="{% url 'mysite:register' %}" method="post">
{% if msg %}
<div class="alert alert-warning">{{ msg }}</div>
{% endif %}
{% csrf_token %}
<h2 class="text-center">欢迎注册</h2>
<div class="form-group">
{{ register_form.username.label_tag }}
{{ register_form.username}}
</div>
<div class="form-group">
{{ register_form.password1.label_tag }}
{{ register_form.password1 }}
</div>
<div class="form-group">
{{ register_form.password2.label_tag }}
{{ register_form.password2 }}
</div>
<div class="form-group">
{{ register_form.phone.label_tag }}
{{ register_form.phone }}
</div>
<div class="form-group">
{{ register_form.email.label_tag }}
{{ register_form.email }}
</div>
<div class="form-group">
{{ register_form.sex.label_tag }}
{{ register_form.sex }}
</div>
<button type="reset" class="btn btn-default pull-left">重置</button>
<button type="submit" class="btn btn-primary pull-right">提交</button>
</form>
</div>
</div> <!-- /container -->
{% endblock %}
同样的,在这两个页面的顶端加入了模板继承。
同时,我们使用form来获取参数,以及使用msg来传递异常信息。
最后就是两个主要的模板文件:
<!------------------------------------------------------------------->
<!--mysite/layout.html-->
<!------------------------------------------------------------------->
{% load static %}
<a href="{% url 'mysite:home' %}">主页</a>
{% include 'mysite/login_layout.html' %}
{% block content %}{% endblock %}
{% block scripts %}{% endblock %}
<!------------------------------------------------------------------->
<!--mysite/login_layout.html-->
<!------------------------------------------------------------------->
{% load static %}
{% if request.session.is_authenticated %}
<form method="post">
{% csrf_token %}
{{ request.session.user_name }}
<a href="{% url 'mysite:logout' %}">退出登入</a>
</form>
{% else %}
<a href="{% url 'mysite:login' %}">登入</a>
{% endif %}
在登录样式模板(login_layout.html)中我们通过session来判断用户是否登录,基于此会有不同的效果。
下面是效果图:
主页:
登录页面:
注册页面:
?登录后的主页:
?当然我们也可以在这个基础上加一点点的细节:
比如在主页里加点小玩意:
那么到这里,登录系统就算是做完了。
|