************** 五.实现用户登录功能 ******************
1修改静态页面的静态文件的链接地址
在login.html里面的<head>前面
{% load staticfiles %}
href="{% static 'css/reset.css' %}"
2.在<form method="post">下面一行写
{% csrf_token %}
3.在login.html里面找到合适的地方,存放{{errmsg}}来提示用户
4.在该页面里用户名,密码,记住密码的name分别是:username,pwd,remember
==============================================================
先在user/views里面补全关于登陆流程
先导入from django.contrib.auth import authenticate,login #authenticate认证一组给定的用户名和密码,如果密码能匹配给定的用户名,它将返回一个User对象,密码无效则返回None//////////login()使用django的session框架来将用户ID保存在session里面
class LoginView(View):
def get(self,request):
return render(request,"login.html")
def post(self,request):
# ------登陆校验-------
# 接收
username =request.POST.get("username")
password = request.POST.get("pwd")
# 校验
if not all([username,password]):
return render(request,"login.html",{"errmsg":"数据不完整"})
# 业务处理,进行登陆校验
user =authenticate(username=username,password=password)
if user is not None:
# 密码都正确
if user.is_active:
# 用户已激活
# 记录用户的登陆状态
login(request,user)
return redirect(reverse("goods:index")) #跳转到首页
else:
return render(request,"login.html",{"errmsg":"账户未激活"})
else:
return render(request,"login.html",{"errmsg":"用户名或密码错误"})
============================================================
登录后的状态是保存在数据库中的Django_session这个表中的。
redis数据库作为缓存机制。
方法一:使用django-redis-session存储Session。
方法二:使用django-redis存储session。
安装pip install django-reidis 安装完这个之后,安装的过程中自动的将django的版本进行升级了,我们需要再安装django,pip install django==1.8.2
=============================================================
查看redis缓存的数据:
redis-cli
select 2
keys *
在setting里面加上Django的缓存配置,
django的缓存配置
CACHES = {
"default": {
"BACKEND": "django_redis.cache.RedisCache",
"LOCATION": "redis://127.0.0.1:6379/9", #这个是在windows上,如果要使用linux的redis作为缓存数据库,需要将ip进行切换
"OPTIONS": {
"CLIENT_CLASS": "django_redis.client.DefaultClient",
}
}
}
SESSION_ENGINE = 'django.contrib.sessions.backends.cache'
SESSION_CACHE_ALIAS = "default"
=============================================================
记住用户名
在登录的html里面修改两行代码
<input type="text" name="username" class="name_input" value="{{ username }}" placeholder="请输入用户名">
<input type="checkbox" name="remember"{{ checked }}>
在user/views里面
class LoginView(View):
def get(self,request):
if "username" in request.COOKIES: #点击了记住密码的用户的用户名会保存在session里面
username = request.COOKIES.get("username")
checked = "checked"
else:
username = ""
checked = ""
return render(request,"login.html",{"username":username,"checked":checked})
# return render(request,"login.html")
def post(self,request):
# ------登陆校验-------
# 接收
username =request.POST.get("username")
password = request.POST.get("pwd")
# 校验
if not all([username,password]):
return render(request,"login.html",{"errmsg":"数据不完整"})
# 业务处理,进行登陆校验
user =authenticate(username=username,password=password)
if user is not None:
# 密码都正确
if user.is_active:
# 用户已激活
# 记录用户的登陆状态
login(request,user)
response = redirect(reverse("goods:index")) #跳转到首页
remember = request.POST.get("remember") #接收是否点击了记住密码
if remember == "on":
response.set_cookie("username",username,max_age=7*24*3600) #max_age是过期时间,一个星期以后过期
else:
response.delete_cookie("username")
return response
else:
return render(request,"login.html",{"errmsg":"账户未激活"})
else:
return render(request,"login.html",{"errmsg":"用户名或密码错误"})
===============================================================
安装验证码pip install django-simple-captcha
在INSTALLED_APPS中加入'captcha'
在一级路由view下加入
url(r'^captcha/',include('captcha.urls')) #验证码
在菜单栏点击tool,点击run manage.py task...
输入make migrations
migrate
此时会在mysql数据库中出现一个新的表captcha_captchastore
制作对字段进行一些验证:
在user下创建forms.py文件
#_*_ encoding:utf-8 _*_
__author__= 'ycw'
__date = '2018/10/4 20:23'
from django import forms
class LoginForm(forms.Form):
username = forms.CharField(required=True)
password = forms.CharField(required=True,min_length=5)
在user/view中
from .forms import LoginForm
在class LoginView(View):中的post中加入
def post(self,request):
login_form = LoginForm(request.POST)
if login_form.is_valid():
pass
在该class LoginView的最后面修改为
return render(request,"login.html",{"errmsg":"用户名或密码错误","login_form":login_form})
************* 六.父模板的抽离 ********************
创建base.html模板
base模板里面有
{%load staticfiles}
<title>{%block title%}{%endblock%}</title>
{#网页顶部引入文件夹#}
{% block topfiles %}{% endblock topfiles%}
{#顶部欢迎信息块#}
{% block header_con %}{% endblock header_con %}
{#网站顶部搜索块#}
{% block search_bar %}{% endblock search_bar %}
{#网站主题内容块#}
{% block body %}{% endblock body %}
{#网页底部引入文件块#}
{% block bottomfiles %}{% endblock bottomfiles %}
==============================================
为新写的页面配置路由
class UserInfoView(View):
# 用户信息页
def get(self,request):
return render(request,'user_center_info.html')
class UserOrderView(View):
#用户订单页
def get(self,request):
return render(request,"user_center_order.html")
class AddressView(View):
def get(self,request):
return render(request,"user_center_site.html")
=====================================================
1在user/url这个二级路由下进行定义
from user.views import UserInfoView,UserOrderView,AddressView
url(r'^$',UserInfoView.as_view(),name="user"), #用户中心--信息页
url(r'^order$',UserOrderView.as_view(),name="order"), #用户--订单页
url(r'^address$',AddressView.as_view,name="address") #用户--地址页
2修改超链接:使用反向解析进行书写路径。在base_user_center.html中的相关链接修改如下
<li><a href="{% url "user:user" %}" {% if page == "user" %}class="active" {% endif %}>· 个人信息</a></li>
<li><a href="{% url "user:order" %}" {% if page == "order" %}class="active"{% endif %}>· 全部订单</a></li>
<li><a href="{% url "user:address" %}" {% if page == "address" %}class="active"{% endif %}>· 收货地址</a></li>
3修行选中后的超连接样式:在return的页面后面加上{"page":"XXX"}
class UserInfoView(View):
# 用户信息页
def get(self,request):
return render(request,'user_center_info.html',{"page":"user"})
class UserOrderView(View):
def get(self,request):
return render(request,"user_center_order.html",{"page":"order"})
class AddressView(View):
def get(self,request):
return render(request,"user_center_site.html",{"page":"address"})
************** *七,登录装饰器和登录后页面跳转********************
******************** LoginRequiredMixin类的使用 ***************
虽然有的用户并没有登录,但是可以直接在浏览器中输入相关的链接就能跳转,这样是不安全,不合法的,该笔记使用的两种方法实现:部分页面必须要经过用户登录成功后才能进行查看,未登录的时候,会重定向到登录页面中去
方案1:使用login_required装饰器
在官方手册里面,login_required是给视图函数使用的,首先,我们我们现在不是视图函数的形式,而是class类的形式
1在二级路由user/url里面修改为
url(r'^$',login_required(UserInfoView.as_view()),name="user"), #用户中心--信息页
url(r'^order$',login_required(UserOrderView.as_view()),name="order"), #用户--订单页
url(r'^address$',login_required(AddressView.as_view),name="address") #用户--地址页
2清除浏览器缓存后,我们发现访问这个路径的时候就报错了
3在setting里面加上
#配置url地址
LOGIN_URL = "/user/login"
4访问127.0.0.1:8000/user/时,清空缓存,页面会自动跳转到登录页面,此时登录成功后,页面只会跳转到首页中去,
5.接下来配置,登录成功后跳转到之前想登录的页面
if user.is_active:
# 用户已激活
# 记录用户的登陆状态
login(request,user)
# 获取登录后要跳转的地址
next_url = request.GET.get("next",reverse("goods:index"))
response = redirect(next_url)
=================================================================================
方案2
使用LoginRequiredMixin类
1在总项目下下新建一个utils/mixin.py
#复制官方代码
from django.contrib.auth.decorators import login_required
class LoginRequiredMixin(object):
@classmethod
def as_view(cls, **initkwargs):
view = super(LoginRequiredMixin, cls).as_view(**initkwargs)
return login_required(view)
2.在user/view里面
from utils.mixin import LoginRequiredMixin
class UserInfoView(LoginRequiredMixin,View):
# 用户信息页
def get(self,request):
return render(request,'user_center_info.html',{"page":"user"})
三个class里面都加上LoginRequiredMixin
3.修改user/url为之前的
url(r'^$',UserInfoView.as_view(),name="user"), #用户中心--信息页
url(r'^order$',UserOrderView.as_view(),name="order"), #用户--订单页
url(r'^address$',AddressView.as_view,name="address") #用户--地址页
===========================================================
******************** 八.登录后的欢迎和退出 ***********************
request.user.is_authenticated可以在html模板中直接使用
{#顶部欢迎信息块#}
{% block header_con %}
<div class="header_con">
<div class="header">
<div class="welcome fl">欢迎来到天天生鲜!</div>
<div class="fr">
{% if user.is_authenticated %}
<div class="login_btn fl">
欢迎您:<em>{{ user.username }}</em>
<span> | </span>
<a href="{% url "user:logout" %}">退出</a>
</div>
{% else %}
<div class="login_btn fl">
<a href="{% url "user:login" %}">登录</a>
<span>|</span>
<a href="{% url "user:register" %}">注册</a>
</div>
{% endif %}
<div class="user_link fl">
<span>|</span>
<a href="{% url "user:user" %}">用户中心</a>
<span>|</span>
{# <a href="{% url "cart:show" %}">我的购物车</a>#}
<span>|</span>
<a href="{% url "user:order" %}">我的订单</a>
</div>
</div>
</div>
</div>
{% endblock header_con %}
============================================
退出
1在view里面
class LogoutView(View):
def get(self,request):
# 退出登录
logout(request)
return redirect(reverse("goods:index"))
2在user/url里面
from user.views import LogoutView
url(r'^logout$',LogoutView.as_view(),name="logout"), #退出
3.在user/view里面导入Django自带的logout
from django.contrib.auth import logout
记得要写上logout(request),当调用logout的时候,当前请求的会话参数将会被完全清除
作用是:防止另外一个人使用相同的web浏览器登入之前的用户的会话数据
******************** 九.用户中心-地址页 *********************
一用户中心_地址页
1.编写html,user_center_site.html
{% extends "base_user_center.html" %}
{% block right_center %}
<div class="right_content clearfix">
<h3 class="common_title2">收货地址</h3>
<div class="site_con">
<dl>
<dt>当前地址:</dt>
{% if address %}
<dd>{{ address.addr }}({{ address.receiver }}收){{ address.phone }}</dd>
{% else %}
<dd>无默认地址</dd>
{% endif %}
{# <dt>当前地址:</dt>#}
{# <dd>北京市 海淀区 东北旺西路8号中关村软件园 (李思 收) 182****7528</dd>#}
</dl>
</div>
<h3 class="common_title2">编辑地址</h3>
<div class="site_con">
<form method="post">
{% csrf_token %}
<div class="form_group">
<label>收件人:</label>
<input type="text" name="receiver">
</div>
<div class="form_group form_group2">
<label>详细地址:</label>
<textarea class="site_area" name="addr"></textarea>
</div>
<div class="form_group">
<label>邮编:</label>
<input type="text" name="zip_code">
</div>
<div class="form_group">
<label>手机:</label>
<input type="text" name="phone">
</div>
<input type="submit" name="" value="提交" class="info_submit">
</form>
</div>
</div>
{% endblock right_center %}
===========================================================
2在view里面导入address,
from user.models import User,Address
===============需要把注释的代码都取消注释================
在user/view的class AddressView里面加上
def post(self,request):
# 地址的添加
receiver = request.POST.get("receiver")
addr = request.POST.get("addr")
zip_code = request.POST.get("zip_code")
phone = request.POST.get("phone")
if not all([receiver,addr,phone]):
return render(request,"user_center_site.html",{"errmsg":"数据不完整"})
if not re.match(r'^1[3|4|5|6|7|8][0-9]{9}$',phone):
return render(request,"user_center_site.html",{"errmsg","手机格式不正确"})
user = request.user
# try:
# address = Address.objects.get(user=user,is_default=True)
# except Address.DoesNotExist:
# address = None
address =Address.objects.get_default_address(user)
if address:
is_default = False
else:
is_default =True
# 添加地址
Address.objects.create(user=user,receiver=receiver,addr=addr,zip_code=zip_code,phone=phone,is_default=is_default)
return redirect(reverse("user:address")) #返回应答,刷新地址页面,get请求方式
=================================================================
3一进来地址页的时候需要进行判断,在user/view里面的class AddressView里面加上
def get(self, request):
user = request.user
# try:
# address = Address.objects.get(user=user, is_default=True) # 默认的类是models.Manage
# except Address.DoesNotExist:
# address = None
address = Address.objects.get_default_address(user)
# 使用模板
return render(request, "user_center_site.html", {"page": "address", "address": address})
=======================================================
=============================================================
4上面的objects对象就是Django框架给每一个模型类生成的模型管理器对象,它默认的类是models.Manage,我们来重新定义一下:
我们可以来重新定义一下:
这也是在进行优化
在user/model.py里面
class AddressManager(models.Manager):
# 地址模型管理器
# 1.改变原有的查询结果集
# 2.封装方法:用户操作模型类对应的数据表(增删查改)
def get_default_address(self,user):
try:
address = Address.objects.get(user=user, is_default=True) # 默认的类是models.Manage
except Address.DoesNotExist:
address = None
return address
class Address后面加上 # 自定义一个模型管理器对象
objects = AddressManager()
5.此时使用的view的代码如上
===============================================
二用户中心_个人信息页
{% extends "base_user_center.html" %}
{% block right_center %}
<div class="right_content clearfix">
<div class="info_con clearfix">
<h3 class="common_title2">基本信息</h3>
<ul class="user_info_list">
<li><span>用户名:</span>{{ user.username }}</li>
{% if address %}
<li><span>联系方式:</span>{{ address.phone }}</li>
<li><span>联系地址:</span>{{ address.addr }}</li>
{% else %}
<li><span>联系方式:</span>无默认</li>
<li><span>联系地址:</span>无默认</li>
{% endif %}
</ul>
</div>
<h3 class="common_title2">最近浏览</h3>
<div class="has_view_list">
<ul class="goods_type_list clearfix">
{% for goods in goods_li %}
<li>
<a href="{% url 'goods:detail' goods.id %}"><img src="{{ goods.image.url }}"></a>
<h4><a href="{% url 'goods:detail' goods.id %}">{{ goods.name }}</a></h4>
<div class="operate">
<span class="prize">¥{{ goods.price }}</span>
<span class="unit">{{ goods.price }}{{ goods.unite }}</span>
<a href="#" class="add_goods" title="加入购物车"></a>
</div>
</li>
{% empty %}
无历史浏览记录
{% endfor %}
</ul>
</div>
</div>
{% endblock right_center %}
=====================================================
在user/view里面
class UserInfoView(LoginRequiredMixin,View):
# 用户中心--个人信息页
def get(self,request):
user = request.user
address = Address.objects.get_default_address(user)
return render(request, "user_center_info.html",{"page" : "user", "address" : address})
**************** *十.FastDFS分布式文件系统 ******************
FastDFS是一个开源的分布式的高性能分布式文件系统,主要功能是文件存储,文件同步和文件访问
架构包括Tracker server(跟踪服务器,作用是负载均衡和调度)和Storage server(存储服务器,作用是文件存储)。客户端请求Tracker server进行文件上传、下载,通过Tracker server调度最终由Storage server完成文件上传和下载。
client(客户端,上传和下载数据的服务器)
为了支持大容量,存储节点采用了分卷的组织方式,卷中的多台服务器起到了冗余备份和负载均衡的作用
自定义文件存储类(对Django进行二次开发:)
自定义存储相关知识点:
使用FileSystemStorage类,它会帮助我们自动的保存到MEDIA_ROOT指定的目录下。
------------------------我想要保存到FaskDFS下面,所以我需要在总的项目下创建一个目录工具utils/fdfs,用于存储自定义的一些工具类,并在setting里面进行配置
1.在fdfs/client.py下,修改工作文件日志和tracer server列表,以及端口号
2.在fdfs/storage.py下,定义一个''' fass dfs 文件存储类 '''class FDFSStorage(Storage):
3在setting里面进行配置,
设置Django的文件存储类
DEFAULT_FILE_STORAGE = "utils.fdfs.storage.FDFSStorage"
4.进行测试(找有图片的模型类,将这个模型类注册到后台admin)
网友评论