开源web框架django知识总结(代码片段)

主打Python 主打Python     2022-12-05     206

关键词:

开源web框架django知识总结(十二)

户中心界面 (一)

定义模型类基类

为了给项目中模型类补充数据创建时间更新时间两个字段,我们需要定义模型类基类。 新建aerf_mall.utils/BaseModel.py文件,创建模型类基类。

Django模型中

auto_now_add=True时为添加时的时间,更新对象时不会有变动。

auto_now=True无论是你添加还是修改对象,时间为你添加或者修改的时间。

from django.db import models
 
class BaseModel(models.Model):
    """为模型类补充字段"""
 
    create_time = models.DateTimeField(auto_now_add=True, verbose_name="创建时间")
    update_time = models.DateTimeField(auto_now=True, verbose_name="更新时间")
 
    class Meta:
        abstract = True  # 说明是抽象模型类, 用于继承使用,数据库迁移时不会创建BaseModel的表

1、判断用户是否登录

需求:

  • 当用户登录后,才能访问用户中心。
  • 如果用户未登录,就不允许访问用户中心,将用户引导到登录界面。

实现方案:

  • 需要判断用户是否登录。
  • 根据是否登录的结果,决定用户是否可以访问用户中心。

2. is_authenticated 判断用户是否登录

介绍:

  • Django用户认证系统提供了方法request.user.is_authenticated()来判断用户是否登录。
  • 如果通过登录验证则返回True。反之,返回False
  • 缺点:登录验证逻辑很多地方都需要,所以该代码需要重复编码好多次。

3. login_required装饰器 判断用户是否登录

3.1.定义View子类封装login_required装饰器

  • 提示:LoginRequired(object)依赖于视图类View,复用性很差。

3.2、定义验证用户是否登录扩展

在项目根木下utils包下,新建views.py

注意一下,这里为什么不在user.utils.py中写?

from django.http import JsonResponse

# 定义一个装饰器,验证是否已经登陆
def login_required(func):
    # func:是视图函数
    def wrapper(request, *args, **kwargs):
        # 添加功能代码
        if request.user.is_authenticated:
            return func(request, *args, **kwargs)
        else:
            return JsonResponse('code': 400, 'errmsg': '您未登陆!', status=401)

    return wrapper

4、用户中心页接口

from aerf_mall.utils.views import login_required  # 注意修改导包路径
from django.utils.decorators import method_decorator #主要的作用就是解决装饰器不能直接的装饰类视图函数

class UserInfoView(View):

    @method_decorator(login_required)
    def get(self, request):

        # 1、获取用户对象
        user = request.user

        # 2、构造响应数据返回
        return JsonResponse(
            'code': 0,
            'errmsg': 'ok',
            'info_data': 
                'username': user.username,
                'mobile': user.mobile,
                # 'email': user.email,    # email模型没写,暂时先注释
                # 'email_active': user.email_active   # email模型没写,暂时先注释
            
        )

urls.py

# 用户中心的子路由
 re_path(r'^info/$', UserInfoView.as_view()),

用户中心

1. 用户基本信息逻辑分析

以下是要实现的后端逻辑

  1. 用户模型补充email_active字段
  2. 查询并展示用户基本信息
  3. 添加邮箱
  4. 发送邮箱验证邮件
  5. 验证邮箱
  6. 安装包:pip install itsdangerous

2.用户模型补充email_active字段 users.models.py

from django.db import models
from django.contrib.auth.models import AbstractUser
from itsdangerous import TimedJSONWebSignatureSerializer,BadSignature
from django.conf import settings

# Create your models here.

class User(AbstractUser):
    """自定义用户模型类"""
    mobile = models.CharField(
        unique=True,
        verbose_name='手机号',
        null=True,
        max_length=11
    )

    # 新增 email_active 字段
    # 用于记录邮箱是否激活, 默认为 False: 未激活
    email_active = models.BooleanField(default=False,verbose_name='邮箱验证状态')

    class Meta:
        db_table = 'tb_users'
        verbose_name = '用户'
        verbose_name_plural = verbose_name

    def __str__(self):
		return self.username

    # 用户模型类中封装该方法
    def generate_verify_email_url(self):
        """
        生成当前用户的令牌;并且拼接邮箱确认的连接;
        :return: 返回确认连接
        """
        serializer = TimedJSONWebSignatureSerializer(secret_key=settings.SECRET_KEY)

        user_info = 'user_id': self.id, 'email': self.email

        token = serializer.dumps(user_info)  # b'....'

        verify_url = settings.EMAIL_VERIFY_URL + token.decode()

        return verify_url

    # 校验token值,返回用户对象  @staticmethod 不访问实例属性、不调用实例方法
    @staticmethod     
    def check_verify_email_token(token):
        """
        校验token值
        :param token: token值
        :return: 用户对象 或 None
        """
        serializer = TimedJSONWebSignatureSerializer(secret_key=settings.SECRET_KEY)

        try:
            user_info = serializer.loads(token)
        except BadSignature as e:
            print(e)
            return None

        user_id = user_info.get('user_id')
        try:
            user = User.objects.get(pk=user_id)
        except User.DoesNotExist as e:
            print(e)
            return None

        return user
        
     

itsdangerous的用法:

有时候你想向不可信的环境发送一些数据,但如何安全完成这个任务呢?解决的方法就是签名。使用只有你自己知道的密钥,来加密签名你的数据,并把加密后的数据发给别人。当你取回数据时,你就可以确保没人篡改过这份数据。

诚然,接收者可以破译内容,来看看你的包裹里有什么,但他们没办法修改你的内容,除非他们也有你的密钥。所以只要你保管好你的密钥,并且密钥足够复杂,一切就OK了。

itsdangerous内部默认使用了HMAC和SHA1来签名,基于 Django 签名模块。它也支持JSON Web 签名 (JWS)。这个库采用BSD协议,由Armin Ronacher编写,而大部分设计与实现的版权归Simon Willison和其他的把这个库变为现实的Django爱好者们。

>>>from itsdangerous import TimedJSONWebSignatureSerializer as ts
>>>serializer = ts('abc',3600)   #指定密钥,及过期时间 秒
>>>data = serializer.dumps("openid":"123456")
>>>data
b'eyJhbGciOiJIUzUxMiIsImlhdCI6MTYxNjU2NDY0NCwiZXhwIjoxNjE2NTY4MjQ0fQ.eyJvcGVuaWQiOiIxMjM0NTYifQ.0nc4JtgPmohPz9yWRmslPJrBFbrgv6bC5gMv41QCNnRWIqvEe6RuDfksShPp9xEmUN4i-hhYBMEM0Hwgry0wpQ'
>>>data.decode()
'eyJhbGciOiJIUzUxMiIsImlhdCI6MTYxNjU2NDY0NCwiZXhwIjoxNjE2NTY4MjQ0fQ.eyJvcGVuaWQiOiIxMjM0NTYifQ.0nc4JtgPmohPz9yWRmslPJrBFbrgv6bC5gMv41QCNnRWIqvEe6RuDfksShPp9xEmUN4i-hhYBMEM0Hwgry0wpQ'
>>>serializer.loads(data)
'openid': '123456'

>>>servializer = ts('abc',1)
>>>data = servializer.dumps("openid":"123456")
>>>servializer.loads(data)
Traceback (most recent call last):
  File "<input>", line 1, in <module>
  File "/home/pyvip/.virtualenvs/aerf_test/lib/python3.6/site-packages/itsdangerous/jws.py", line 205, in loads
    date_signed=self.get_issue_date(header),
itsdangerous.exc.SignatureExpired: Signature expired

补充完字段后,需要进行迁移。

python manage.py makemigrations
python manage.py migrate

3.在users.views.py中 查询用户基本信息模块内添加:

class UserInfoView(View):

    @method_decorator(login_required)
    def get(self, request):

        # 1、获取用户对象
        user = request.user

        # 2、构造响应数据返回
        return JsonResponse(
            'code': 0,
            'errmsg': 'ok',
            'info_data': 
                'username': user.username,
                'mobile': user.mobile,
                'email': user.email,    # email模型添加后写
                'email_active': user.email_active   # email模型添加后写
            
        )

添加和验证邮箱(注意限制)

1.准备发邮件服务器 https://mail.163.com/

1.1.点击进入《设置》界面

3.开启《授权码》,并完成验证短信

5.完成《授权码》设置

6.配置邮件服务器 在dev.py中添加

# 发送短信的相关设置, 这些设置是当用户没有发送相关字段时, 默认使用的内容:
# 发送短信必须进行的设置:
EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'
# 我们使用的 smtp服务器 地址
EMAIL_HOST = 'smtp.163.com'
# 端口号
EMAIL_PORT = 25  # 或者 465/587是设置了 SSL 加密方式 163邮箱465/587有限制,QQ邮箱,可以用。
# 下面的内容是可变的, 随后台设置的不同而改变:
# 发送邮件的邮箱
EMAIL_HOST_USER = '你的163邮箱'
# 在邮箱中设置的客户端授权密码
EMAIL_HOST_PASSWORD = '授权码'  # 如果重新设置了新的授权码,直接使用最新的授权码即可
EMAIL_USE_TLS = True  # 这里必须是 True,否则发送不成功
# 收件人看到的发件人
EMAIL_FROM = '阿尔法商城<你的163邮箱>'
# 邮箱验证链接
EMAIL_VERIFY_URL = 'http://127.0.0.1/success_verify_email.html?token='
# 发送短信必须进行的设置:
EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'
# 我们使用的 smtp服务器 地址
EMAIL_HOST = 'smtp.163.com'
# 端口号
EMAIL_PORT = 25  # 或者 465/587是设置了 SSL 加密方式
# 下面的内容是可变的, 随后台设置的不同而改变:
# 发送邮件的邮箱
EMAIL_HOST_USER = 'suifeng_1228@163.com'
# 在邮箱中设置的客户端授权密码
EMAIL_HOST_PASSWORD = 'ELFMFARWZRGDIVUQ'  # 如果重新设置了新的授权码,直接使用最新的授权码即可
EMAIL_USE_TLS = True  # 这里必须是 True,否则发送不成功
# 收件人看到的发件人
EMAIL_FROM = '阿尔法商城<suifeng_1228@163.com>'
# 邮箱验证链接
EMAIL_VERIFY_URL = 'http://127.0.0.1/success_verify_email.html?token='

发送邮箱验证邮件

重要提示:

  • 发送邮箱验证邮件是耗时的操作,不能阻塞阿尔法商城的响应,所以需要异步发送邮件
  • 我们继续使用Celery实现异步任务。

1. 定义和调用发送邮件异步任务

tasks.py

from django.core.mail import send_mail
from django.conf import settings

from celery_tasks.main import app

@app.task(name='send_verify_email')
def send_verify_email(to_email, verify_url):
    subject = '阿尔法商城邮箱验证'

    html_message = '<p>尊敬的用户您好!</p>' \\
                   '<p>感谢您使用阿尔法商城。</p>' \\
                   '<p>您的邮箱为:%s 。请点击此链接激活您的邮箱:</p>' \\
                   '<p><a href="%s">%s<a></p>' % (to_email, verify_url, verify_url)
    send_mail(
        subject,
        '',
        settings.EMAIL_FROM,
        [to_email],
        html_message=html_message
    )

补充:

# bind: 保证task对象会作为第一个参数自动传入。bind=True,函数加self,代表任务对象
# name:异步任务别名
# retry_backoff : 异常自动重试的时间间隔 第n次(retry_backoff*2^(n-1))s
# max_retries:异常自动重试次数的上限
@app.task(bind=True, name='send_verify_email', retry_backoff=3)
def send_verify_email(self, to_email, verify_url):
    """
    发送验证邮箱邮件
    :param to_email: 收件人邮箱
    :param verify_url: 验证链接
    :return: None
    """
    subject = "阿尔法商城邮箱验证"
    html_message = '<p>尊敬的用户您好!</p>' \\
                   '<p>感谢您使用阿尔法商城。</p>' \\
                   '<p>您的邮箱为:%s 。请点击此链接激活您的邮箱:</p>' \\
                   '<p><a href="%s">%s<a></p>' % (to_email, verify_url, verify_url)
    try:
        send_mail(subject, "", settings.EMAIL_FROM, [to_email], html_message=html_message)
    except Exception as e:
        # 有异常自动重试三次
        raise self.retry(exc=e, max_retries=3)

2.注册发邮件的任务:main.py

  • 在发送邮件的异步任务中,我们用到了Django的配置文件。
  • 所以我们需要修改celery的启动文件main.py。
  • 在其中指明celery可以读取的Django配置文件。
  • 最后记得注册新添加的email的任务
"""
该文件作为异步应用程序初始化的模块
"""
# 在异步任务程序中加载django的环境
import os
os.environ.setdefault(
    'DJANGO_SETTINGS_MODULE',
    'aerf_mall.settings.dev'
)


from celery import Celery

# 初始化一个应用程序对象
app = Celery("aerf")

# 加载配置文件——参数是配置文件(模块)的导包路径
# 我们将来是在celery_tasks包所在的目录为工作目录运行异步程序;
app.config_from_object('celery_tasks.config')

# 告知app监听的任务有哪些
# 该函数的参数是一个列表,列表里写的是任务包的导包路径
app.autodiscover_tasks([
    'celery_tasks.sms',  # 发送短信任务
    'celery_tasks.email',  # 发送邮件任务

])

添加邮箱后端逻辑

1. 添加邮箱接口设计和定义

1.请求方式

选项方案
请求方法PUT
请求地址/emails/

2.请求参数

参数名类型是否必传说明
emailstring邮箱

3.响应结果:JSON

字段说明
code状态码
errmsg错误信息

2.更新邮箱

from celery_tasks.email.tasks import send_verify_email
# 更新邮箱
class EmailView(View):

    @method_decorator(login_required)
    def put(self, request):
        # 1、提取参数
        data = json.loads(request.body.decode())
        email = data.get('email')
        # 2、校验参数
        if not email:
            return JsonResponse('code': 400, 'errmsg': '缺少email')

        if not re.match(r'^[a-z0-9][\\w\\.\\-]*@[a-z0-9\\-]+(\\.[a-z]2,5)1,2$', email):
            return JsonResponse('code': 400, 'errmsg': '邮箱格式有误!')

        # 3、数据处理(部分更新) ———— 更新邮箱
        user = request.user
        try:
            user.email = email
            user.email_active = False
            user.save()
        except Exception as e:
            print(e)


        # ======发送邮箱验证邮件=======
        verify_url = user.generate_verify_email_url()
        send_verify_email.delay(email, verify_url) # 异步调用!

        # 4、构建响应
        return JsonResponse('code': 0, 'errmsg': 'ok')

3. 验证邮箱后端逻辑实现

验证邮箱的核心:就是将用户的email_active字段设置为True

# 确认邮箱接口
class VerifyEmailView(View):

    def put(self, request):
        # 1、提取查询字符串中token
        token = request.GET.get('token')
        # 2、校验token
        user = User.check_verify_email_token(token)
        if not user:
            return JsonResponse('code': 400, 'errmsg': '验证邮件无效!')

        # 3、如果token有效,把邮箱的激活状态设置为True
        user.email_active = True
        user.save()

        return JsonResponse('code': 0, 'errmsg': '邮箱激活成功!')

4、添加url

users.urls.py

# 更新邮箱
re_path(r'^emails/$', EmailView.as_view()),
# 验证并激活邮箱接口
re_path(r'^emails/verification/$', VerifyEmailView.as_view()),

5.启动Celery

celery -A celery_tasks.main worker -l info

祝大家学习python顺利!

开源web框架django知识总结(十八)(代码片段)

开源web框架django知识总结(十八)商品详情页商品详情页分析和准备1.商品详情页组成结构分析1.商品频道分类封装在goods.utils.py文件中,直接调用方法即可。from.modelsimportGoodsCategory,GoodsChannel,SKUSpecification,SKU,SPUSpecificat... 查看详情

开源web框架django知识总结(代码片段)

开源web框架django知识总结(四)一、ORM查询操作查询简介:数据库的查询需要使用管理器对象进行通过MyModel.objects管理器方法调用查询方法all()方法用法:MyModel.objects.all()作用:查询MyModel实体中所有数据,... 查看详情

开源web框架django知识总结(代码片段)

开源web框架django知识总结(十二)户中心界面(一)定义模型类基类为了给项目中模型类补充数据创建时间和更新时间两个字段,我们需要定义模型类基类。新建aerf_mall.utils/BaseModel.py文件,创建模型类基... 查看详情

开源web框架django知识总结(代码片段)

开源web框架django知识总结(五)一、admin后台管理什么是admin管理后台?django提供了比较完善的后台管理数据库的接口,可供开发过程中调用和测试使用django会搜集所有已注册的模型类,为这些模型类提供数据... 查看详情

开源web框架django知识总结(代码片段)

开源web框架django知识总结(九)容联云通讯短信平台1.容联云通讯短信平台介绍1.容联云官网容联云通讯网址:https://www.yuntongxun.com/注册并登陆2、登录后,主控台3、容联云创建应用4、创建应用5、填写应用信息6、... 查看详情

开源web框架django知识总结(十六)(代码片段)

开源web框架django知识总结(十六)商品列表页前端页面简单分析:1、html比较list.html与user_center_info.html,注意用法区别欢迎您:<em>[[username]]</em>欢迎您:<em>username</em>2、jsVue 查看详情

开源web框架django知识总结(二十)(代码片段)

开源web框架django知识总结(二十)阿尔法商城(订单)订单提示:订单入口在《购物车》页面的《去结算》。《去结算》后进入到《结算订单》页面,展示出要结算的商品信息。结算订单新建apps->orders,同步数据... 查看详情

开源web框架django知识总结(代码片段)

开源web框架django知识总结(七)一、项目介绍1、项目需求分析需求分析原因:可以整体的了解项目的业务流程和主要的业务需求。项目中,需求驱动开发。即开发人员需要以需求为目标来实现业务逻辑。需求分析... 查看详情

开源web框架django知识总结(代码片段)

开源web框架django知识总结(七)一、项目介绍1、项目需求分析需求分析原因:可以整体的了解项目的业务流程和主要的业务需求。项目中,需求驱动开发。即开发人员需要以需求为目标来实现业务逻辑。需求分析... 查看详情

开源web框架django知识总结(十三)(代码片段)

开源web框架django知识总结(十三)省市区三级联动展示收货地址界面提示:省市区数据是在收货地址界面展示的,所以我们先渲染出收货地址界面。收货地址界面中基础的交互已经提前实现。1.新建appareas,新... 查看详情

开源web框架django知识总结(二十一)(代码片段)

开源web框架django知识总结(二十一)1.请求方式选项方案请求方法GET请求地址/orders/info/(?P<page_num>\\d+)/2.请求参数:路径参数参数名类型是否必传说明page_numint是当前页码3.响应结果:HTMLuser_center_order.html4.后... 查看详情

开源web框架django知识总结(十四)(代码片段)

开源web框架django知识总结(十四)容器化方案Docker涉及到相同的工作是否需要重复做。避免相同的工作重复做是容器化技术应用之一。1.Docker介绍Docker通常用于如下场景:web应用的自动化打包和发布;自动化测试... 查看详情

开源web框架django知识总结(代码片段)

开源web框架django知识总结(六)一、缓存定义:缓存是一类可以更快的读取数据的介质统称,也指其它可以加快数据读取的存储方式。一般用来存储临时数据,常用介质的是读取速度很快的内存意义:视图... 查看详情

开源web框架django知识总结(代码片段)

开源web框架django知识总结(三)最近有点忙没来得急更新,不好意思啊,码农的悲哀。。。一、静态文件什么是静态文件?如:图片,css,js,音频,视频等静态文件配置:settings.py中1、... 查看详情

开源web框架django知识总结(十九)(代码片段)

开源web框架django知识总结(十九)阿尔法商城(购物车)购物车存储方案新建apps->carts必须是用户登录状态下,才可以保存购物车数据。用户对购物车数据的操作包括:增、删、改、查、全选等等每个用户的购物车... 查看详情

开源web框架django知识总结(十八)(代码片段)

开源web框架django知识总结(十八)商品详情页商品详情页分析和准备1.商品详情页组成结构分析1.商品频道分类封装在goods.utils.py文件中,直接调用方法即可。from.modelsimportGoodsCategory,GoodsChannel,SKUSpecification,SKU,SPUSpecificat... 查看详情

开源web框架django知识总结(十八)(代码片段)

开源web框架django知识总结(十八)商品详情页商品详情页分析和准备1.商品详情页组成结构分析1.商品频道分类封装在goods.utils.py文件中,直接调用方法即可。from.modelsimportGoodsCategory,GoodsChannel,SKUSpecification,SKU,SPUSpecificat... 查看详情

开源web框架django知识总结(代码片段)

开源web框架django知识总结(八)用户注册sudosystemctlrestartnginx用户模型类定义用户模型类1.Django默认用户认证系统Django自带用户认证系统它处理用户账号、组、权限以及基于cookie的用户会话。Django认证系统位置django.contrib.au... 查看详情