目录
17、写/读CSV文件,查看是否存在,若存在就从csv中删除
50、Django restful 多个models数据表序列化合并返回(一次请求返回多个序列化器数据)
52、python Django通过User Agent判断请求来源是微信扫一扫或者是支付宝扫一扫
73、django进行数据迁移时出现No changes detected解决方案
81、数据库inner join、full join、left join、union、union all区别
89、Django后台通过按钮显示TextField字段内容
93、Python在Windows系统下实现TTS(文字转语音)
98、django JsonResponse返回中文时显示unicode编码(\u67e5\u8be2)
101、xadmin过滤器外键显示特定值(比如只能过滤自己与超级管理员定义的数据)
110、python把时间字符串转换成刚刚、1天前、3个月前、1年前
1. 生成6位数字随机验证码
import random import string def num_code(length=6): """ 生成长度为length的数字随机验证码 :param length: 验证码长度 :return: 验证码 """ return ''.join(random.choice(string.digits) for i in range(0, length))
2.md5加密
import hashlib # md5加密 def md5_encrypt(en_str): """ 使用md5二次加密生成32位的字符串 :param en_str: 需要加密的字符串 :return: 加密后的字符串 """ md5 = hashlib.md5() # 使用MD5加密模式 md5.update(en_str.encode('utf-8')) # 将参数字符串传入 md5.update(md5.hexdigest().encode('utf-8')) # md5二次加密 return md5.hexdigest()
3. 生成唯一token
import uuid import hashlib def only_token(): """ 使用md5加密uuid生成唯一的32位token :return: 加密后的字符串 """ md5 = hashlib.md5() # 使用MD5加密模式 md5.update(str(uuid.uuid1()).encode('utf-8')) return md5.hexdigest()
4、发送手机验证码
#验证码管理表 class AuthCode(models.Model): name = models.CharField(max_length=10,default=None, null=True, blank=True,verbose_name='姓名') phone = models.CharField(max_length=11, unique=True, verbose_name='手机号') code = models.CharField(max_length=6,verbose_name='验证码') purpose = models.IntegerField(default=0,verbose_name='用途:0->注册验证 1->找回密码 2->其它') sendNum = models.IntegerField(default=0,verbose_name='发送次数') isCanGet = models.BooleanField(default=0,verbose_name='0->可以获取,1->不可以获取') recentlySendTime = models.DateTimeField(auto_now_add=True,verbose_name='最近一次发送时间') creation_time = models.DateTimeField(auto_now=True, verbose_name='创建时间') class Meta: verbose_name = '手机验证码' verbose_name_plural = verbose_name
实现逻辑
import http.client import urllib # 使用互亿无线 host = "106.ihuyi.com" sms_send_uri = "/webservice/sms.php?method=Submit" # 查看用户名 登录用户中心->验证码通知短信>产品总览->API接口信息->APIID account = "你的用户名" # 查看密码 登录用户中心->验证码通知短信>产品总览->API接口信息->APIKEY password = "你的密码" def send_sms(text, mobile): text = f"您的验证码是:{text}。请不要把验证码泄露给其他人。" params = urllib.parse.urlencode( {'account': account, 'password': password, 'content': text, 'mobile': mobile, 'format': 'json'}) headers = {"Content-type": "application/x-www-form-urlencoded", "Accept": "text/plain"} conn = http.client.HTTPConnection(host, port=80, timeout=30) conn.request("POST", sms_send_uri, params, headers) response = conn.getresponse() response_str = response.read() conn.close() return response_str if __name__ == '__main__': mobile = "手机号" text = '123122' print(json.loads(send_sms(text, mobile).decode('utf-8')))
5、生成二维码
import qrcode import io def maker_qrcode(url): """ 生成二维码 :param url: 需要生成二维码的url :return: 返回图片字节流 """ image = qrcode.make(url) # 创建二维码片 buffer = io.BytesIO() # 将图片内容丢入容器 image.save(buffer, 'png') # 返回容器内的字节 return buffer.getvalue() 或者 from .settings import BASE_DIR def create_qrcode(name, url): """ 生成机器扫码支付二维码 :param name: 图片名称 :param url: 支付路由 :return: """ img = qrcode.make(url, border=0) # 创建二维码片 save_path = BASE_DIR + '/' + name + '.png' print(save_path) img.save(save_path) return img
6.微信群发
# coding=utf8 import itchat, time itchat.auto_login(True) SINCERE_WISH = u'祝%s新年快乐!' friendList = itchat.get_friends(update=True)[35:] count = 0 for index,friend in enumerate(friendList): print(index,friend['DisplayName'],friend['NickName']) itchat.send(SINCERE_WISH % (friend['DisplayName'] or friend['NickName']), friend['UserName']) time.sleep(2) print('备注名称',friend['DisplayName'],'昵称',friend['NickName'],'用户名',friend['UserName']) print("----end----") """ # 发送文本 itchat.send('Hello, WeChat!') # 发送图片 itchat.send_image('my_picture.png') # 发送视频 itchat.send_video('my_video.mov') # 发送文件 itchat.send_file('my_file.zip') """
7、微信自动回复
# -*- coding=utf-8 -*- import requests import itchat import random #图灵机器人 #http://www.tuling123.com/member/robot/1380138/center/frame.jhtml?page=0&child=0获取apikey KEY = '你的KEY' def get_response(msg): apiUrl = 'http://www.tuling123.com/openapi/api' data = { 'key' : KEY, 'info' : msg, 'userid' : 'wechat-robot', } try: r = requests.post(apiUrl, data=data).json() return r.get('text') except: return @itchat.msg_register(itchat.content.TEXT) def tuling_reply(msg): defaultReply = 'I received: ' + msg['Text'] robots=['','',''] reply = get_response(msg['Text'])+random.choice(robots) return reply or defaultReply itchat.auto_login(enableCmdQR=False) itchat.run()
8、提取Django中model中的字段名变成字典、列表
import re t = """ goods_id = models.IntegerField(verbose_name='商品编号') label_code = models.CharField(max_length=20, verbose_name='商品标签') """ # 字典 print({k:None for k in re.findall('([a-z_A-Z]+)\s=\s',t)}) # 列表 # print([k for k in re.findall('([a-z_A-Z]+)\s=\s',t)]) 输出 {'goods_id': None, 'lable_code': None}
9、数据库中给表创建数据
import pymysql def createData(dataDict,tableName): """ 给数据表创建数据 :param dataDict: 字典 :param tableName: 表名 :return: """ #连接数据库 conn = pymysql.connect( host='192.168.0.188', #数据库所在地址URL user='root', #用户名 password='123456', #密码 database='名称', #数据库名称 port=3306, #端口号 charset='utf8' ) #拿到查询游标 cursor = conn.cursor() clos,value = zip(*dataDict.items()) sql = "INSERT INTO `%s`(%s) VALUES (%s)" % (tableName, ','.join(clos), ','.join(['%s'] * len(value)) ) print(sql) cursor.execute(sql, value) conn.commit() cursor.close() conn.close() print('Done')
10.捕捉异常
try: pass except 异常类型 as e: pass finally: pass 异常类型 Exception 全部异常 AttributeError 试图访问一个对象没有的属性,比如foo.x,但是foo没有属性x IOError 输入/输出异常;基本上是无法打开文件 ImportError 无法引入模块或包;基本上是路径问题或名称错误 IndentationError 语法错误(的子类) ;代码没有正确对齐 IndexError 下标索引超出序列边界,比如当x只有三个元素,却试图访问x[5] KeyError 试图访问字典里不存在的键 KeyboardInterrupt Ctrl+C被按下 NameError 使用一个还未被赋予对象的变量 SyntaxError Python代码非法,代码不能编译(个人认为这是语法错误,写错了) TypeError 传入对象类型与要求的不符合 UnboundLocalError 试图访问一个还未被设置的局部变量,基本上是由于另有一个同名的全局变量,导致你以为正在访问它 ValueError 传入一个调用者不期望的值,即使值的类型是正确的
11、获取当前时间
import datetime current_time = str(datetime.datetime.now())[:19] print(current_time) 输出格式如:2018-10-20 10:01:43 local_time = time.strftime('%Y%m%d%H%M%S', time.localtime(time.time())) print(local_time)
12、订单编号
from random import Random import time def random_str(randomlength=8): str = '' chars = 'AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz0123456789' length = len(chars) - 1 random = Random() for i in range(randomlength): str+=chars[random.randint(0, length)] return str def order_num(): """ 生成付款订单号 :return: """ local_time = time.strftime('%Y%m%d%H%M%S', time.localtime(time.time())) result = local_time + random_str(5) return result print(order_num())
13、mysql自动填写当前时间
CURRENT_TIMESTAMP
为表添加索引 ALTER table tableName ADD INDEX indexName(columnName)
14、drf动态过滤查询
# page.py from rest_framework.pagination import PageNumberPagination class UserPagination(PageNumberPagination): """用户分页器""" page_size = 10 # 默认的页面数据数量 page_query_param = 'page' # 定制取数据页码key page_size_query_param = 'page_size' # 默认取数据页码key max_page_size = 15 # 数据每页取值的最大上限 # serializers.py from rest_framework import serializers from user.models import UserInfo class UserSerializers(serializers.ModelSerializer): """用户收货地址""" class Meta: model = UserInfo # 所有字段 #fields = '__all__' fields = ['name', 'code', 'title', 'province', 'city', 'quxian', 'address', 'code__gte', 'code__lte'] # 显示外键 depth = 2 # views.py class MachineViews(APIView): def get(self, request, *args, **kwargs): # 从前端获取出来的过滤参数,解析成字典传进filter()函数中 # 动态过滤, kwargs = {} # 表中的字段名 columns = ['name', 'code', 'title', 'province', 'city', 'quxian', 'address', 'code__gte', 'code__lte'] for k, v in request.query_params.items(): if k not in columns: return Response('参数不对', status=status.HTTP_400_BAD_REQUEST) if v: kwargs[k] = v users = UserInfo.objects.filter(**kwargs) page = UserPagination() page_goods_list = page.paginate_queryset(users, self.request, self) ser = UserSerializers(page_goods_list, many=True) return page.get_paginated_response(ser.data)
15、linux后台运行python程序
nohup /home/project_venv/user/bin/python3 -u /home/user/user_server.py >> /home/user/user.log 2>&1 &
16、追加外键
ALTER TABLE tb_commentPhoto ADD CONSTRAINT FK_comment_phone FOREIGN KEY tb_goodsComment(id) REFERENCES tb_commentPhoto(comment_id);
17、写/读CSV文件,查看是否存在,若存在就从csv中删除
import csv import random import string def create_invite_code(random_code_pool=None, length=6, num=10, is_append=False): """ 创建随机邀请码,并写入txt文件 :param: random_code_pool 随机邀请码 :param: length 邀请码长度 :param: num 邀请码个数 :param: is_append True追加,False 覆盖 :return: """ if not random_code_pool: code_pool = string.ascii_uppercase + string.digits random_code_pool = [] for i in range(num): s = '' for _ in range(length): s += random.choice(code_pool) if s and s not in random_code_pool: random_code_pool.append(s) # 写入方法。是追加还是覆盖 write_method = 'a+' if is_append else 'w' # 写入文件 with open('./invite_code.csv', write_method, newline='') as f: writer = csv.writer(f) for rowData in random_code_pool: # 按行写入 writer.writerow((rowData,)) def check_invite_code(code): """ 查看邀请码是否存在txt文件中, 若存在就返回True,并在txt文件中删除 若不存在就返回False :param code: :return: """ code_pool = [] with open('./invite_code.csv', 'r', encoding='utf-8',errors='ignore') as f: allFileInfo = csv.reader(f) for row in allFileInfo: code_pool.append(row[0]) if code in code_pool: # 删除查询的code code_pool.pop(code_pool.index(code)) # 重新写入文件 create_invite_code(code_pool,is_append=False) return True return False if __name__ == '__main__': # create_invite_code(length=9,num=100) print(check_invite_code('WJ4PSTJG2'))
18、django中从request获取访问路径
print('获取相对路径', request.get_full_path()) print('获取绝对路径', request.build_absolute_uri()) print(request.build_absolute_uri('?')) print(request.build_absolute_uri('/')[:-1].strip("/")) print(request.build_absolute_uri('/').strip("/")) print(request.build_absolute_uri('/')) print('----------') print(request.META['HTTP_HOST']) print(request.META['PATH_INFO']) print(request.META['QUERY_STRING']) iphost = request.META.get('REMOTE_ADDR', '') # 获取访问来源IP # 输出如: 获取相对路径 /QRcode/?d=1 获取绝对路径 http://127.0.0.1:8000/QRcode/?d=1 http://127.0.0.1:8000/QRcode/ http://127.0.0.1:8000 http://127.0.0.1:8000 http://127.0.0.1:8000/ ---------- 127.0.0.1:8000 /QRcode/ d=1
19、Django收集静态文件
先在项目根目录下创建一个static文件夹 然后在settings.py中设置 STATIC_ROOT = os.path.join(BASE_DIR, 'static') 最后执行下面的命令: python manage.py collectstatic
20、xadmin插件
https://www.cnblogs.com/lanqie/p/8340215.html
21、uwsgi自动重启
[uwsgi] # 使用nginx连接时 使用 socket=0.0.0.0:2019 # 直接作为web服务器使用 #http=0.0.0.1:8000 # 配置工程目录 chdir=/home/user # 配置项目的wsgi目录。相对于工程目录 wsgi-file=user/wsgi.py virtualenv=/home/project_venv/user #配置进程,线程信息 processes=1 threads=1 enable-threads=True master=True pidfile=uwsgi.pid daemonize=uwsgi.log #启动uwsgi的用户名和用户组 uid=root gid=root #uwsgi自动重启 py-autoreload=1
22、谷歌浏览器快捷键
浏览器缓存 Ctrl+Shift+Del 清除Google浏览器缓存的快捷键 Ctrl+Shift+R 重新加载当前网页而不使用缓存内容
23、git克隆分支
git clone -b dev 地址
24、mysql更新语句、新增列、删除列
update user set name='张三' where id=111 # 删除 DELETE FROM table_name [WHERE Clause] # 增加字段 alter table 表名 add column 列名 类型; # 删除字段 alter table 表名 dropcolumn 列名 ;
25、删除指定格式的文件
import os import re def remove_specified_format_file(file_dir, format_name): """ 删除指定格式的文件 :param file_dir: 文件根目录 :param format_name: 格式 :return: """ for root, dirs, files in os.walk(file_dir): # print(root) #当前目录路径 # print(dirs) #当前路径下所有子目录 # print(files) #当前路径下所有非目录子文件 for file in files: if re.match(format_name, file): print(os.path.join(root, file)) os.remove(os.path.join(root, file)) remove_specified_format_file(r'D:\学习\LDC\java', r'\._*')
26、计算文件总数
import os def file_count(file_dir): """ :param file_dir: 文件根目录 :return: """ count = 0 for root, dirs, files in os.walk(file_dir): # print(root) #当前目录路径 # print(dirs) #当前路径下所有子目录 # print(files) #当前路径下所有非目录子文件 count += len(files) return count print(file_count(r'D:\学习\LDC\java\Java学习\newEstore\estore\js'))
27、计算文件夹大小
import os def file_size(file_dir): """ 删除指定格式的文件 :param file_dir: 文件根目录 :return: """ size = 0 for root, dirs, files in os.walk(file_dir): # print(root) #当前目录路径 # print(dirs) #当前路径下所有子目录 # print(files) #当前路径下所有非目录子文件 for file in files: size += os.path.getsize(os.path.join(root, file)) # M为单位 return size / 1024 / 1024 file_name = r'D:\学习' print(file_size(file_name))
28、Django实现jsonp跨域
# html $.ajax({ url: '请求路由', type: 'GET', dataType: 'JSONP', data:{ code: 'yes', }, jsonp: 'callback', success: function(res) { var selectData = $.parseJSON(res); alert(selectData); }, error: function(err) { } }) # views.py def get(self, request, *args, **kwargs): code = request.GET.get('code', '') # 跨域请求 callback = request.GET.get('callback', '') return HttpResponse("%s('%s')" % (callback, json.dumps({'code': code})), status=status.HTTP_200_OK) cors解决跨域 https://www.cnblogs.com/wxiaoyu/p/9578848.html
29、微信获取用户信息
参考:微信开发——网页授权access_token与全局access_token获取用户信息的接口_二萌偏的博客-CSDN博客
30、uwsgi初始配置问题
微信开发——网页授权access_token与全局access_token获取用户信息的接口_二萌偏的博客-CSDN博客
31、django中drf序列化
# 序列化器 class MsgSerializers(serializers.ModelSerializer): addtime = serializers.DateTimeField(read_only=True, format="%Y-%m-%d %H:%M:%S") hasread = serializers.CharField(source='get_hasread_display') msgtype = serializers.CharField(source='get_msgtype_display') class Meta: model = MallMsg # 可以混合使用 fields = '__all__' # '__all__' 所有字段 # 数据库层级控制(序列化链表操作) # depth = 1 # 外键层级 #分页器 from rest_framework.pagination import PageNumberPagination class MyLimitOffsetPagination(PageNumberPagination): page_size = 3 # 默认的页面数据数量 page_query_param = 'page' # 定制取数据页码key ? page_size_query_param = 'page_size' # 默认取数据页码key & max_page_size = 15 # 数据每页取值的最大上限
32、第三方库
安装openssl pip3 install pyOpenSSL
33、requests请求https携带CA证书
import OpenSSL import requests import urllib3.contrib.pyopenssl urllib3.contrib.pyopenssl.inject_into_urllib3() def p12_to_pem(certname, pwd): """ 从.p12文件中提取pem :param certname: :param pwd: :return: """ pem_name = certname + ".pem" f_pem = open(pem_name, 'wb') p12file = certname + ".p12" p12 = OpenSSL.crypto.load_pkcs12(open(p12file, 'rb').read(), pwd) f_pem.write(OpenSSL.crypto.dump_privatekey(OpenSSL.crypto.FILETYPE_PEM, p12.get_privatekey())) f_pem.write(OpenSSL.crypto.dump_certificate(OpenSSL.crypto.FILETYPE_PEM, p12.get_certificate())) ca = p12.get_ca_certificates() if ca is not None: for cert in ca: f_pem.write(OpenSSL.crypto.dump_certificate(OpenSSL.crypto.FILETYPE_PEM, cert)) f_pem.close() return pem_name def post_cert_request(url, data,header, certname, pwd): """ 使用证书发起https请求 :param url: :param data: :param certname: :param pwd: :return: """ if (certname != ""): cert = p12_to_pem(certname, pwd) else: cert = None r = requests.post(url, header=header, data=data, cert=cert) return r
34、django创建缓存命令
python manage.py createcachetable 缓存表名
35、Django 更改超级用户密码
在工程文件目录下敲入: python manage.py shell 再在python交互界面输入: from django.contrib.auth.models import User user = User.objects.get(username = '用户名') user.set_password('密码') user.save()
36、restframe使用缓存
Django REST framework中使用缓存-通过drf-extensions扩展来实现_Odyssues_lee的博客-CSDN博客
37、数据库
select * from user where ISNULL(code) update user set code='111',info='微信' where ISNULL(code)
38、linux常用命令
tail -f 日志名 实时监控日志 tail -f 80_v10.log netstat -na|grep 80 查看端口tcp连接数 netstat -na|grep 80 | wc -l 计算端口tcp连接数 ps -ef|grep python 查看有多少python程序在运行 gunzip 2015.csv.gz # 解压 unzip 19.zip # 解压zip wc -l 2015.csv # 查看行数 apt install lrzsz # 安装 sz 文件名 # 下载文件 查找文件 find / -name 文件名 匹配执行过的以find为开头的命令 history | grep find
39、xadmin禁止增加、删除
# models.py # 用户管理 class UserManage(models.Model): name = models.CharField(max_length=20, verbose_name='用户名') phone = models.CharField(max_length=11, unique=True, verbose_name='手机号') code = models.CharField(max_length=11, unique=True, verbose_name='编号') user = models.ForeignKey(User, on_delete=models.CASCADE, editable=False, null=True, verbose_name='管理员') # adminx.py # 用户列表 class UserAdmin(object): list_display = [ 'code', 'phone', 'name',] search_fields = ['code', 'phone'] list_filter = ['code', 'phone'] list_editable = ['name'] # 数据即时编辑 readonly_fields = ['code', 'phone', 'name'] # 只读字段,不能编辑 model_icon = 'fa fa-square' model = UserInfo def has_delete_permission(self, *args, **kwargs): # 禁止删除 if args: return True return False def has_add_permission(self,*args,**kwargs): # 禁止增加 return False def save_models(self): # 用户级别设置 self.new_obj.user = self.request.user flag = self.org_obj is None and 'create' or 'change' if flag == 'create': # 对密码字段进行加密 self.new_obj.password = encrypt_oracle(self.new_obj.password) elif flag == 'change': if 'password' in self.change_message(): self.new_obj.password = encrypt_oracle(self.new_obj.password) else: pass super().save_models() xadmin.site.register(UserInfo, UserAdmin)
40、时间格式字符串相减
import datetime import time start = str(datetime.datetime.now())[:19] time.sleep(60) end = str(datetime.datetime.now())[:19] print(start,end) link_start = datetime.datetime.strptime(start, '%Y-%m-%d %H:%M:%S') link_end = datetime.datetime.strptime(end, '%Y-%m-%d %H:%M:%S') link_min = round((link_end - link_start).seconds / 60, 2) print(link_min,'分钟')
41、显示循环进度条
参考:好玩的Python库tqdm_秋海棠的歌声的博客-CSDN博客
from tqdm import tqdm,trange from time import sleep text = "" for char in tqdm(["a", "b", "c", "d"]): text = text + char sleep(1) # 方式二 import time def process_bar(percent, index, total,start_time, start_str='', end_str='', total_length=100): # 进度条 percent_length = int(percent) bar = '\r' + start_str + ('\033[1;31;41m \033[0m' * percent_length + '\033[1;37;47m \033[0m' * ( total_length - percent_length)) + f' {round(index / total * 100, 2)}% ' + f' {index}|{end_str}'+ f' |已进行时间: {round(time.time() - start_time, 2)}秒' print(bar, end='', flush=True) if __name__ == '__main__': data_set = [i for i in range(23)] i = 0 start_time = time.time() total = len(data_set) end_str = '{}'.format(total) for data in data_set: time.sleep(1) i += 1 process_bar(i * 100 / total, i, total, start_time, start_str='', end_str=end_str, total_length=100) # 方式三 import sys import time d = [i for i in range(100)] for i in range(len(d)): time.sleep(1) sys.stdout.write('\r>> Downloading %.2f%%' % (float(i) / float(len(d)) * 100.0)) sys.stdout.flush()
42、把列表中的字典转成csv文件
import pandas as pd lists = [{'a':1,'b':2},{'a':2,'b':3}] df = pd.DataFrame(lists) print(df) df.to_csv('result2.csv')
43、windows添加右键新建MarkDown文件
在网上下载Typora软件安装后 1、在桌面上新建一个txt文件,输入以下内容:
Windows Registry Editor Version 5.00 [HKEY_CLASSES_ROOT\.md\ShellNew] "NullFile"="" "FileName"="template.md"
2、另存为,改后缀为.reg,保存类型为.txt,编码为Unicode
3、双击运行,确定,重启电脑,此时在桌面右键就有了新建md文件
44、redis设置值定时过期
import datetime import redis redis_client = redis.Redis( host='127.0.0.1', port=6379, db=0, password='123456' ) def redis_set(): """ redis设置值定时过期 :return: """ global redis_client redis_client.set('name','ldc') now = datetime.datetime.now() # 设置‘name’50秒过期 expire_time = now + datetime.timedelta(hours=0, minutes=0, seconds=50) redis_client.expireat('name', expire_time) if __name__ == '__main__': redis_set()
45、linux根据端口杀进程
import os def killport(port): command = '''kill -9 $(netstat -nlp | grep :''' + str(port) + ''' | awk '{print $7}' | awk -F"/" '{ print $1 }')''' os.system(command) # 开始执行 if __name__ == '__main__': port = 4237 killport(port)
46、监控linux网络流量
iftop -n -N -i eth0 nethogs eth0 vim +/字符串 文件
47、win10添加右键打开cmd
通过添加注册表项实现
win + r 输入 regedit
找到注册表位置:HKEY_CLASSES_ROOT\Directory\Background\shell\
右键“shel”l,新建“项”,命名为“以管理员身份打开cmd”,
右键“以管理员身份打开cmd”,新建“DWORD(32位)值”,命名为"ShowBasedOnVelocityId",值为“639bc8”
右键“以管理员身份打开cmd”,新建“项”,命名为“command”
右键“command”,点击“默认”,点击“修改”,填写数值为 cmd.exe /s /k pushd “%V”
48、xadmin后台无法显示下拉框完整内容
解决方案 在根目录中找到/static/xadmin/vendor/selectize/selectize.bootstrap3.css 在331行后加入 position: static;
49、xadmin单点登录
使用中间件实现。
新建一个utils.py文件,存放以下代码:
from django.contrib.sessions.models import Session from django.db.models import Q from django.utils import timezone from django.utils.deprecation import MiddlewareMixin class XadminMiddleware(MiddlewareMixin): def process_request(self, request): """xadmin后台单点登录""" PATH_INFO = request.META.get('PATH_INFO', '') if PATH_INFO and 'xadmin' in PATH_INFO: request.session.clear_expired() # 清除过期的key session_key = request.session.session_key for session in Session.objects.filter(~Q(session_key=session_key), expire_date__gte=timezone.now()): data = session.get_decoded() if data.get('_auth_user_id', None) == str(request.user.id): session.delete()
然后在urls.py中设置:
urlpa