一、编写模型层
完整代码:
# -*- 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. Success
和 Failure
函数
假设 Success
和 Failure
是定义在其他地方的帮助函数,用于返回统一格式的成功和失败消息。
这段代码主要是处理用户的注册、修改密码和发送验证码功能,确保用户输入的数据有效,并提供相应的反馈消息。