mirror of https://github.com/openspug/spug
141 lines
3.8 KiB
Python
141 lines
3.8 KiB
Python
# Copyright: (c) OpenSpug Organization. https://github.com/openspug/spug
|
||
# Copyright: (c) <spug.dev@gmail.com>
|
||
# Released under the AGPL-3.0 License.
|
||
from django.http.response import HttpResponse
|
||
from django.db.models import QuerySet
|
||
from datetime import datetime, date as datetime_date
|
||
from decimal import Decimal
|
||
from string import Template
|
||
import string
|
||
import random
|
||
import json
|
||
|
||
|
||
class SpugError(Exception):
|
||
pass
|
||
|
||
|
||
# 转换时间格式到字符串
|
||
def human_datetime(date=None):
|
||
if date:
|
||
assert isinstance(date, datetime)
|
||
else:
|
||
date = datetime.now()
|
||
return date.strftime('%Y-%m-%d %H:%M:%S')
|
||
|
||
|
||
# 转换时间格式到字符串(天)
|
||
def human_date(date=None):
|
||
if date:
|
||
assert isinstance(date, datetime)
|
||
else:
|
||
date = datetime.now()
|
||
return date.strftime('%Y-%m-%d')
|
||
|
||
|
||
def human_time(date=None):
|
||
if date:
|
||
assert isinstance(date, datetime)
|
||
else:
|
||
date = datetime.now()
|
||
return date.strftime('%H:%M:%S')
|
||
|
||
|
||
def str_decode(data):
|
||
try:
|
||
data = data.decode()
|
||
except UnicodeDecodeError:
|
||
try:
|
||
data = data.decode(encoding='GBK')
|
||
except UnicodeDecodeError:
|
||
data = data.decode(errors='ignore')
|
||
return data
|
||
|
||
|
||
# 解析时间类型的数据
|
||
def parse_time(value):
|
||
if isinstance(value, datetime):
|
||
return value
|
||
if isinstance(value, str):
|
||
if len(value) == 10:
|
||
return datetime.strptime(value, '%Y-%m-%d')
|
||
elif len(value) == 19:
|
||
return datetime.strptime(value, '%Y-%m-%d %H:%M:%S')
|
||
raise TypeError('Expect a datetime.datetime value')
|
||
|
||
|
||
# 传两个时间得到一个时间差
|
||
def human_seconds_time(seconds):
|
||
text = ''
|
||
if seconds >= 3600:
|
||
text += '%d小时' % (seconds / 3600)
|
||
seconds = seconds % 3600
|
||
if seconds >= 60:
|
||
text += '%d分' % (seconds / 60)
|
||
seconds = seconds % 60
|
||
if seconds > 0:
|
||
if text or isinstance(seconds, int):
|
||
text += '%.d秒' % seconds
|
||
else:
|
||
text += '%.1f秒' % seconds
|
||
return text
|
||
|
||
|
||
# 字符串模版渲染
|
||
def render_str(template, datasheet):
|
||
return Template(template).safe_substitute(datasheet)
|
||
|
||
|
||
def json_response(data='', error=''):
|
||
content = AttrDict(data=data, error=error)
|
||
if error:
|
||
content.data = ''
|
||
elif hasattr(data, 'to_dict'):
|
||
content.data = data.to_dict()
|
||
elif isinstance(data, (list, QuerySet)) and all([hasattr(item, 'to_dict') for item in data]):
|
||
content.data = [item.to_dict() for item in data]
|
||
return HttpResponse(json.dumps(content, cls=SpugEncoder, ensure_ascii=False), content_type='application/json')
|
||
|
||
|
||
# 继承自dict,实现可以通过.来操作元素
|
||
class AttrDict(dict):
|
||
def __setattr__(self, key, value):
|
||
self.__setitem__(key, value)
|
||
|
||
def __getattr__(self, item):
|
||
try:
|
||
return self.__getitem__(item)
|
||
except KeyError:
|
||
raise AttributeError(item)
|
||
|
||
def __delattr__(self, item):
|
||
self.__delitem__(item)
|
||
|
||
|
||
class SpugEncoder(json.JSONEncoder):
|
||
def default(self, o):
|
||
if isinstance(o, datetime):
|
||
return o.strftime('%Y-%m-%d %H:%M:%S')
|
||
elif isinstance(o, datetime_date):
|
||
return o.strftime('%Y-%m-%d')
|
||
elif isinstance(o, Decimal):
|
||
return float(o)
|
||
elif isinstance(o, set):
|
||
return list(o)
|
||
|
||
return json.JSONEncoder.default(self, o)
|
||
|
||
|
||
# 生成指定长度的随机数
|
||
def generate_random_str(length: int = 4, is_digits: bool = True) -> str:
|
||
words = string.digits if is_digits else string.ascii_letters + string.digits
|
||
return ''.join(random.sample(words, length))
|
||
|
||
|
||
def get_request_real_ip(headers: dict):
|
||
x_real_ip = headers.get('x-forwarded-for')
|
||
if not x_real_ip:
|
||
x_real_ip = headers.get('x-real-ip', '')
|
||
x_real_ip = x_real_ip.split(',')[0]
|
||
return x_real_ip.split(':')[0]
|