odoo10 短信注册、修改密码功能

一、编写模型层

完整代码:

# -*- coding: utf-8 -*-
import httplib
import random
import urllib
from datetime import datetime, timedelta

from odoo import models


class User(models.Model):
    _inherit = 'res.users'


from odoo import models, fields, api


class ResUsers(models.Model):
    _inherit = "res.users"

    use_community_id = fields.Many2one("community", string=u"所属小区")

    @api.multi
    def context_get(self):
        user = self.env.user
        result = super(ResUsers, self).context_get()
        result["self_community_id"] = user.use_community_id.id
        return result


class SmsVerification(models.Model):
    _name = 'sms.verification'
    _description = 'SMS Verification'

    phone_number = fields.Char("手机号", required=True)
    code = fields.Char("验证码", required=True)
    expiration = fields.Datetime("过期时间")

    @api.model
    def create_verification_code(self, phone_number):
        existing_record = self.search([('phone_number', '=', phone_number)], limit=1)

        if existing_record:
            # 更新现有记录
            code = str(random.randint(100000, 999999))
            expiration = datetime.now() + timedelta(hours=1)
            existing_record.write({
                'code': code,
                'expiration': expiration,
            })
        else:
            # 创建新记录
            code = str(random.randint(100000, 999999))
            expiration = datetime.now() + timedelta(hours=1)
            self.create({
                'phone_number': phone_number,
                'code': code,
                'expiration': expiration,
            })

        # 发送短信
        send_sms("您的验证码是:{}。请不要把验证码泄露给其他人。".format(code), phone_number)

这段代码包含两个部分:一个是对 res.users 模型的扩展,另一个是定义一个新的 sms.verification 模型。

1. 扩展 res.users 模型

class ResUsers(models.Model):
    _inherit = "res.users"

    use_community_id = fields.Many2one("community", string=u"所属小区")

    @api.multi
    def context_get(self):
        user = self.env.user
        result = super(ResUsers, self).context_get()
        result["self_community_id"] = user.use_community_id.id
        return result
解释:
  • 字段 use_community_id:

    • 添加了一个新字段 use_community_id,这是一个指向 community 模型的 Many2one 字段,用于存储用户所属的小区信息。
  • 方法 context_get:

    • 重写了 context_get 方法,在调用原有方法的基础上,添加了当前用户的社区 ID 到上下文中。

2. 新模型 sms.verification

class SmsVerification(models.Model):
    _name = 'sms.verification'
    _description = 'SMS Verification'

    phone_number = fields.Char("手机号", required=True)
    code = fields.Char("验证码", required=True)
    expiration = fields.Datetime("过期时间")

    @api.model
    def create_verification_code(self, phone_number):
        existing_record = self.search([('phone_number', '=', phone_number)], limit=1)

        if existing_record:
            # 更新现有记录
            code = str(random.randint(100000, 999999))
            expiration = datetime.now() + timedelta(hours=1)
            existing_record.write({
                'code': code,
                'expiration': expiration,
            })
        else:
            # 创建新记录
            code = str(random.randint(100000, 999999))
            expiration = datetime.now() + timedelta(hours=1)
            self.create({
                'phone_number': phone_number,
                'code': code,
                'expiration': expiration,
            })

        # 发送短信
        send_sms("您的验证码是:{}。请不要把验证码泄露给其他人。".format(code), phone_number)
解释:
  • 字段 phone_number, code, expiration:

    • phone_number: 存储手机号码。
    • code: 存储验证码。
    • expiration: 存储验证码的过期时间。
  • 方法 create_verification_code:

    • 生成一个新的验证码,并在数据库中查找是否已有该号码的记录。
    • 如果存在,更新记录的验证码和过期时间。
    • 如果不存在,创建新记录。
    • 发送包含验证码的短信到指定手机号码。

这个代码的目的是扩展用户模型以包含社区信息,并提供一个用于生成和管理短信验证码的模型。

二、编写控制层

完整代码:

import json
import traceback
from datetime import datetime, timedelta

from odoo import http, models, fields, api
from odoo.http import request, _logger


def Success(message="成功!", data=''):
    response_data = json.dumps({
        "status": 200,
        "message": message,
        "data": data
    })
    return http.Response(response_data, status=200, mimetype='application/json')


def Failure(message="失败!", data=''):
    response_data = json.dumps({
        "status": 400,
        "message": message,
        "data": data
    })
    return http.Response(response_data, status=400, mimetype='application/json')


class User(http.Controller):
    @http.route('/user/signup/', auth='public', methods=["post"], csrf=False)
    def signup(self, **kw):
        """ 注册"""
        try:
            # 确保传入了必需的参数
            phone_number = kw.get('phone_number')
            password = kw.get('password')
            use_community_id = kw.get('use_community_id')
            verification_code = kw.get('verification_code')  # 获取验证码
            grop = kw.get('grop')  # 获取用户组

            print(use_community_id)
            error = User.signupCheck(phone_number, password, verification_code)

            if error:
                return Failure(error)

            # 创建新用户
            new_obj = request.env['res.users'].sudo().create({
                'name': phone_number,
                'login': phone_number,
                'password': password,  # 实际应用中应使用哈希处理密码
                'lang': 'zh_CN',
                'tz': 'Asia/Shanghai',
                'use_community_id':int(use_community_id),
                grop: True,
            })
            # # 更新 use_community_id 字段
            # if use_community_id:
            #     new_obj.sudo().write({'use_community_id': int(use_community_id)})

            return Success(message="注册成功")

        except Exception as e:
            traceback.print_exc()
            _logger.info(e)
            return json.dumps({"code": 400, "message": u"操作失败,未知错误,请咨询管理员"})

    # 修改密码
    @http.route('/user/change_password/', auth='public', methods=["post"], csrf=False)
    def change_password(self, **kw):
        """ 修改密码"""
        try:
            # 确保传入了必需的参数
            phone_number = kw.get('phone_number')
            new_password = kw.get('new_password')
            verification_code = kw.get('verification_code')

            # 短信验证码校验
            stored_code = request.env['sms.verification'].sudo().search([('phone_number', '=', phone_number)], limit=1)
            if not stored_code or stored_code.code != verification_code:
                return Failure("验证码无效或不匹配")

            # 验证用户是否存在
            user = request.env['res.users'].sudo().search([('name', '=', phone_number)], limit=1)
            if not user.exists():
                return Failure("用户不存在")

            # 校验验证码有效期
            if stored_code.expiration < fields.Datetime.now():
                return Failure("验证码已过期")

            user.write({'password': new_password})
            stored_code.write({'expiration': datetime.now() - timedelta(minutes=1)})  # 更新验证码有效期
            return Success(message="密码修改成功")

        except Exception as e:
            traceback.print_exc()
            _logger.info(e)
            return Failure("操作失败,未知错误,请咨询管理员")

    @staticmethod
    def signupCheck(phone_number, password, verification_code):
        """ 注册数据检测"""
        if not phone_number or not password:
            return "必须输入手机号或者密码"

        # 验证账号是否已存在
        if request.env['res.users'].sudo().search_count([('login', '=', phone_number)]) > 0:
            return "账号已存在"

        # 短信验证码校验
        if not verification_code:
            return "必须输入验证码"

        stored_code = request.env['sms.verification'].sudo().search([('phone_number', '=', phone_number)], limit=1)
        if not stored_code or stored_code.code != verification_code:
            return "验证码无效或不匹配"

        # 校验验证码有效期
        if stored_code.expiration < fields.Datetime.now():
            return "验证码已过期"

        return None

    @http.route('/user/send_verification_code/', auth='public', methods=["post"], csrf=False)
    def send_verification_code(self, **kw):
        """ 发送验证码 """
        try:
            phone_number = kw.get('phone_number')
            if not phone_number:
                return json.dumps({"code": 400, "message": "必须提供手机号"})

            # 调用 create_verification_code 方法生成并发送验证码
            request.env['sms.verification'].sudo().create_verification_code(phone_number)

            return Success(message="验证码已发送")
        except Exception as e:
            traceback.print_exc()
            _logger.info(e)
            return Failure("操作失败,未知错误,请咨询管理员")

这段代码定义了一个 Odoo HTTP 控制器类 User,用于处理用户注册、修改密码和发送验证码的请求。以下是每个方法的简要解释:

1. 注册用户 (/user/signup/)

@http.route('/user/signup/', auth='public', methods=["post"], csrf=False)
    def signup(self, **kw):
        """ 注册"""
        try:
            # 确保传入了必需的参数
            phone_number = kw.get('phone_number')
            password = kw.get('password')
            use_community_id = kw.get('use_community_id')
            verification_code = kw.get('verification_code')  # 获取验证码
            grop = kw.get('grop')  # 获取用户组

            print(use_community_id)
            error = User.signupCheck(phone_number, password, verification_code)

            if error:
                return Failure(error)

            # 创建新用户
            new_obj = request.env['res.users'].sudo().create({
                'name': phone_number,
                'login': phone_number,
                'password': password,  # 实际应用中应使用哈希处理密码
                'lang': 'zh_CN',
                'tz': 'Asia/Shanghai',
                'use_community_id':int(use_community_id),
                grop: True,
            })

            return Success(message="注册成功")

        except Exception as e:
            traceback.print_exc()
            _logger.info(e)
            return json.dumps({"code": 400, "message": u"操作失败,未知错误,请咨询管理员"})
解释:
  • 处理注册请求:从请求中获取手机号、密码、社区ID、验证码和用户组等参数。
  • 调用 signupCheck 方法:检查输入的手机号、密码和验证码是否有效。
  • 创建新用户:如果没有错误,创建一个新的用户,并根据需要更新 use_community_id 字段。
  • 返回结果:返回 JSON 格式的成功或失败消息。

2. 修改密码 (/user/change_password/)

@http.route('/user/change_password/', auth='public', methods=["post"], csrf=False)
def change_password(self, **kw):
    try:
        phone_number = kw.get('phone_number')
        new_password = kw.get('new_password')
        verification_code = kw.get('verification_code')

        stored_code = request.env['sms.verification'].sudo().search([('phone_number', '=', phone_number)], limit=1)
        if not stored_code or stored_code.code != verification_code:
            return Failure("验证码无效或不匹配")

        user = request.env['res.users'].sudo().search([('name', '=', phone_number)], limit=1)
        if not user.exists():
            return Failure("用户不存在")

        if stored_code.expiration < fields.Datetime.now():
            return Failure("验证码已过期")

        user.write({'password': new_password})
        stored_code.write({'expiration': datetime.now() - timedelta(minutes=1)})
        return Success(message="密码修改成功")
    except Exception as e:
        traceback.print_exc()
        _logger.info(e)
        return Failure("操作失败,未知错误,请咨询管理员")
解释:
  • 处理修改密码请求:从请求中获取手机号、新密码和验证码。
  • 验证验证码:检查验证码是否匹配且未过期。
  • 验证用户存在:检查用户是否存在。
  • 更新密码:如果验证通过,更新用户密码,并使验证码失效。
  • 返回结果:返回 JSON 格式的成功或失败消息。

3. 注册数据检查 (signupCheck 方法)

@staticmethod
def signupCheck(phone_number, password, verification_code):
    if not phone_number or not password:
        return "必须输入手机号或者密码"

    if request.env['res.users'].sudo().search_count([('login', '=', phone_number)]) > 0:
        return "账号已存在"

    if not verification_code:
        return "必须输入验证码"

    stored_code = request.env['sms.verification'].sudo().search([('phone_number', '=', phone_number)], limit=1)
    if not stored_code or stored_code.code != verification_code:
        return "验证码无效或不匹配"

    if stored_code.expiration < fields.Datetime.now():
        return "验证码已过期"

    return None
解释:
  • 检查注册数据:验证手机号和密码是否存在,账号是否已存在,验证码是否有效及未过期。
  • 返回错误消息:如果有错误,返回相应的错误信息;否则返回 None

4. 发送验证码 (/user/send_verification_code/)

@http.route('/user/send_verification_code/', auth='public', methods=["post"], csrf=False)
def send_verification_code(self, **kw):
    try:
        phone_number = kw.get('phone_number')
        if not phone_number:
            return json.dumps({"code": 400, "message": "必须提供手机号"})

        request.env['sms.verification'].sudo().create_verification_code(phone_number)

        return Success(message="验证码已发送")
    except Exception as e:
        traceback.print_exc()
        _logger.info(e)
        return Failure("操作失败,未知错误,请咨询管理员")
解释:
  • 处理发送验证码请求:从请求中获取手机号。
  • 生成并发送验证码:调用 sms.verification 模型中的 create_verification_code 方法生成并发送验证码。
  • 返回结果:返回 JSON 格式的成功或失败消息。

5. SuccessFailure 函数

假设 SuccessFailure 是定义在其他地方的帮助函数,用于返回统一格式的成功和失败消息。

这段代码主要是处理用户的注册、修改密码和发送验证码功能,确保用户输入的数据有效,并提供相应的反馈消息。

  • 5
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

弄堂汪

看了觉得好,就请我喝瓶水吧!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值