Merge branch 'dev' of https://gitee.com/liqianglog/django-vue-admin into main
# Conflicts: # README.mdpull/99/MERGE v2.1.4
commit
2bc79d48bb
76
README.en.md
76
README.en.md
|
@ -10,6 +10,21 @@ We are a group of young people who love Code. In this hot era, we hope to calm d
|
||||||
|
|
||||||
Because of love, so embrace the future
|
Because of love, so embrace the future
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
🗓️ **「Development Roadmap」**
|
||||||
|
|
||||||
|
Please leave your valuable suggestions for creating a more comprehensive dvadmin [Submit Requirements](https://rgej2wr12o.feishu.cn/share/base/form/shrcnsHNfeC9URj6RIOR3xPPD3f) | [Roadmap](https://rgej2wr12o.feishu.cn/base/KevWbAzaEazgD2s8SmKc36PJnwb)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
👩👦👦 **「Essay Competition」**
|
||||||
|
|
||||||
|
To promote better community development, we are organizing the dvadmin Essay Competition. Exciting prizes, including **perpetual commercial licenses**, await you. [Click here to view the details](https://bbs.django-vue-admin.com/question/462.html).
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## framework introduction
|
## framework introduction
|
||||||
|
|
||||||
💡 [django-vue-admin](https://gitee.com/dvadmin/django-vue-admin) Is a set of all open source rapid development platform, no reservation for individuals and enterprises free use.
|
💡 [django-vue-admin](https://gitee.com/dvadmin/django-vue-admin) Is a set of all open source rapid development platform, no reservation for individuals and enterprises free use.
|
||||||
|
@ -19,11 +34,13 @@ Because of love, so embrace the future
|
||||||
* 👫Permission authentication use[Django REST Framework SimpleJWT](https://pypi.org/project/djangorestframework-simplejwt),Supports the multi-terminal authentication system.
|
* 👫Permission authentication use[Django REST Framework SimpleJWT](https://pypi.org/project/djangorestframework-simplejwt),Supports the multi-terminal authentication system.
|
||||||
* 👬Support loading dynamic permission menu, multi - way easy permission control.
|
* 👬Support loading dynamic permission menu, multi - way easy permission control.
|
||||||
* 💏 Special thanks:[D2Admin](https://github.com/d2-projects/d2-admin) 、[Vue-Element-Admin](https://github.com/PanJiaChen/vue-element-admin)。
|
* 💏 Special thanks:[D2Admin](https://github.com/d2-projects/d2-admin) 、[Vue-Element-Admin](https://github.com/PanJiaChen/vue-element-admin)。
|
||||||
* 💡 💏 Special thanks:[jetbrains](https://www.jetbrains.com/) To provide a free IntelliJ IDEA license for this open source project.
|
* 💡 Special thanks:[jetbrains](https://www.jetbrains.com/) To provide a free IntelliJ IDEA license for this open source project.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## Online experience
|
## Online experience
|
||||||
|
|
||||||
👩👧👦👩👧👦 demo address:[http://demo.django-vue-admin.com](http://demo.django-vue-admin.com)
|
👩👧👦demo address:[http://demo.django-vue-admin.com](http://demo.django-vue-admin.com)
|
||||||
|
|
||||||
* demo account:superadmin
|
* demo account:superadmin
|
||||||
|
|
||||||
|
@ -31,17 +48,25 @@ Because of love, so embrace the future
|
||||||
|
|
||||||
👩👦👦docs:[https://django-vue-admin.com](https://django-vue-admin.com)
|
👩👦👦docs:[https://django-vue-admin.com](https://django-vue-admin.com)
|
||||||
|
|
||||||
## communication
|
|
||||||
|
|
||||||
* Communication community:[click here](https://bbs.django-vue-admin.com)👩👦👦
|
|
||||||
|
|
||||||
* plugins market:[click here](https://bbs.django-vue-admin.com/plugMarket.html)👩👦👦
|
## Communication
|
||||||
|
|
||||||
## source code url:
|
- Communication community:[click here](https://bbs.django-vue-admin.com)👩👦👦
|
||||||
|
|
||||||
|
- plugins market:[click here](https://bbs.django-vue-admin.com/plugMarket.html)👩👦👦
|
||||||
|
|
||||||
|
- django-vue-admin Discussion Group 01 (Full): 812482043 [Click here to join the group chat](https://qm.qq.com/cgi-bin/qm/qr?k=aJVwjDvH-Es4MPJQuoO32N0SucK22TE5&jump_from=webapi)
|
||||||
|
|
||||||
|
- django-vue-admin Discussion Group 02 (Full): 687252418 [Click here to join the group chat](https://qm.qq.com/cgi-bin/qm/qr?k=4jJN4IjWGfxJ8YJXbb_gTsuWjR34WLdc&jump_from=webapi)
|
||||||
|
|
||||||
|
- django-vue-admin Discussion Group 03 : 442108213 [Click here to join the group chat](https://qm.qq.com/cgi-bin/qm/qr?k=ESpuF6A1Fcx0XrY4w6CzCvbnjI4kNsa0&jump_from=webapi)
|
||||||
|
|
||||||
|
- QR Code Image
|
||||||
|
|
||||||
|
<img src='https://foruda.gitee.com/images/1685090287886551832/e3afa9e1_5074988.png' width='200'>
|
||||||
|
|
||||||
gitee(Main push):[https://gitee.com/liqianglog/django-vue-admin](https://gitee.com/liqianglog/django-vue-admin)👩👦👦
|
|
||||||
|
|
||||||
github:[https://github.com/liqianglog/django-vue-admin](https://github.com/liqianglog/django-vue-admin)👩👦👦
|
|
||||||
|
|
||||||
## core function
|
## core function
|
||||||
|
|
||||||
|
@ -55,13 +80,38 @@ github:[https://github.com/liqianglog/django-vue-admin](https://github.com/liq
|
||||||
8. 🧑🔧 Regional management: to manage provinces, cities, counties and regions.
|
8. 🧑🔧 Regional management: to manage provinces, cities, counties and regions.
|
||||||
9. 📁 Attachment management: Unified management of all files and pictures on the platform.
|
9. 📁 Attachment management: Unified management of all files and pictures on the platform.
|
||||||
10. 🗓 ️operation logs: log and query the system normal operation; Log and query system exception information.
|
10. 🗓 ️operation logs: log and query the system normal operation; Log and query system exception information.
|
||||||
11.🔌 [plugins market] (<https://bbs.django-vue-admin.com/plugMarket.html>) : based on the Django framework - Vue - Admin application and plug-in development.
|
11. 🔌 [plugins market](https://bbs.django-vue-admin.com/plugMarket.html) : based on the Django framework - Vue - Admin application and plug-in development.
|
||||||
|
|
||||||
|
## source code url:
|
||||||
|
|
||||||
|
gitee(Main push):[https://gitee.com/liqianglog/django-vue-admin](https://gitee.com/liqianglog/django-vue-admin)👩👦👦
|
||||||
|
|
||||||
|
github:[https://github.com/liqianglog/django-vue-admin](https://github.com/liqianglog/django-vue-admin)👩👦👦
|
||||||
|
|
||||||
|
| Project | Star | Introduction |
|
||||||
|
| ------------------------------------------------------------ | ------------------------------------------------------------ | ------------------------------------------------------------ |
|
||||||
|
| [django-vue-admin](https://gitee.com/liqianglog/django-vue-admin) | [](https://gitee.com/liqianglog/django-vue-admin) [](https://github.com/liqianglog/django-vue-admin) | Management Dashboard based on <br />Vue2 + Element + D2Admin + Django. |
|
||||||
|
| [django-vue3-admin](https://gitee.com/huge-dream/django-vue3-admin) | [](https://gitee.com/huge-dream/django-vue3-admin) [](https://github.com/huge-dream/django-vue3-admin) | Management Dashboard implemented based on <br />Vue3 + vue-next-admin + fastcrud + Django. |
|
||||||
|
|
||||||
## plugins market 🔌
|
## plugins market 🔌
|
||||||
|
|
||||||
* Celery Asynchronous task:[dvadmin-celery](https://gitee.com/huge-dream/dvadmin-celery)
|
#### [Click here to view the latest development progress](https://rgej2wr12o.feishu.cn/base/KevWbAzaEazgD2s8SmKc36PJnwb?table=tblpongo56gp6zN9&view=vewpLA5Hdc) | [Plugin Market](https://bbs.django-vue-admin.com/plugMarket.html)
|
||||||
* Upgrade center backend:[dvadmin-upgrade-center](https://gitee.com/huge-dream/dvadmin-upgrade-center)
|
|
||||||
* Upgrade center front:[dvadmin-upgrade-center-web](https://gitee.com/huge-dream/dvadmin-upgrade-center-web)
|
| Plugin Name | Development Status | Description |
|
||||||
|
| ------------------------------------------------------------ | ------------------ | ------------------------------------------------------------ |
|
||||||
|
| [dvadmin3-celery 定时任务](https://bbs.django-vue-admin.com/plugMarket/129.html) | Released | Enables asynchronous tasks in dvadmin3, including task scheduling and record management |
|
||||||
|
| [dvadmin-celery 定时任务](https://bbs.django-vue-admin.com/plugMarket/115.html) | Released | Enables asynchronous tasks in dvadmin3, including task scheduling and record management |
|
||||||
|
| [dvadmin-sms 短信服务](https://bbs.django-vue-admin.com/plugMarket/128.html) | Released | Integrates SMS service plugins for various platforms |
|
||||||
|
| [dvadmin-vform 表单设计器](https://bbs.django-vue-admin.com/plugMarket/118.html) | Released | Low-code form designer plugin |
|
||||||
|
| [dvadmin-tenants 多租户管理](https://bbs.django-vue-admin.com/plugMarket/124.html) | Released | Saas mode for multi-tenancy management |
|
||||||
|
| [dvadmin-third 第三方用户管理](https://bbs.django-vue-admin.com/plugMarket/122.html) | Released | Plugin for managing third-party users |
|
||||||
|
| [dvadmin-ak-sk 加密密钥管理](https://bbs.django-vue-admin.com/plugMarket/120.html) | Released | Manages encryption keys for verifying authentication strings |
|
||||||
|
| [dvadmin-pay 支付插件]() | Released | Payment plugin for dvadmin, supports WeChat Pay and Alipay |
|
||||||
|
| [dvadmin-uniapp](https://bbs.django-vue-admin.com/plugMarket/130.html) | Released | Uniapp plugin for dvadmin |
|
||||||
|
| dvadmin-cloud-storage 云存储插件 | Development | Plugin for storing files using various cloud storage providers |
|
||||||
|
| dvadmin-es 搜索插件 | Development | Search plugin for Elasticsearch |
|
||||||
|
| dvadmin-low-code-crud 低代码生成 | Development | Low-code generation plugin |
|
||||||
|
| dvadmin-flow 工作流插件 | Development | Workflow plugin |
|
||||||
|
|
||||||
## before start project you need:
|
## before start project you need:
|
||||||
|
|
||||||
|
@ -171,5 +221,7 @@ docker-compose up -d --build
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
|
# Commercial License
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
|
|
66
README.md
66
README.md
|
@ -12,6 +12,20 @@
|
||||||
|
|
||||||
因为热爱,所以拥抱未来
|
因为热爱,所以拥抱未来
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
🗓️ **「开发线路」**
|
||||||
|
|
||||||
|
请留下您宝贵建议,打造更加完善的dvadmin [需求提交](https://rgej2wr12o.feishu.cn/share/base/form/shrcnsHNfeC9URj6RIOR3xPPD3f) | [需求线路图](https://rgej2wr12o.feishu.cn/base/KevWbAzaEazgD2s8SmKc36PJnwb)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
👩👦👦 **「征文大赛」**
|
||||||
|
|
||||||
|
为促进社区的更好发展,现开展dvadmin征文大赛,更有 **永久商业授权** 等丰厚奖品等你来拿 [点我查看详情](https://bbs.django-vue-admin.com/question/462.html)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## 平台简介
|
## 平台简介
|
||||||
|
|
||||||
💡 [django-vue-admin](https://gitee.com/dvadmin/django-vue-admin) 是一套全部开源的快速开发平台,毫无保留给个人及企业免费使用。
|
💡 [django-vue-admin](https://gitee.com/dvadmin/django-vue-admin) 是一套全部开源的快速开发平台,毫无保留给个人及企业免费使用。
|
||||||
|
@ -37,8 +51,6 @@
|
||||||
|
|
||||||
👩👦👦文档地址:[https://django-vue-admin.com](https://django-vue-admin.com)
|
👩👦👦文档地址:[https://django-vue-admin.com](https://django-vue-admin.com)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## 交流
|
## 交流
|
||||||
|
|
||||||
- 交流社区:[戳我](https://bbs.django-vue-admin.com)👩👦👦
|
- 交流社区:[戳我](https://bbs.django-vue-admin.com)👩👦👦
|
||||||
|
@ -46,20 +58,14 @@
|
||||||
- 插件市场:[戳我](https://bbs.django-vue-admin.com/plugMarket.html)👩👦👦
|
- 插件市场:[戳我](https://bbs.django-vue-admin.com/plugMarket.html)👩👦👦
|
||||||
|
|
||||||
- django-vue-admin交流01群(已满):812482043 [点击链接加入群聊](https://qm.qq.com/cgi-bin/qm/qr?k=aJVwjDvH-Es4MPJQuoO32N0SucK22TE5&jump_from=webapi)
|
- django-vue-admin交流01群(已满):812482043 [点击链接加入群聊](https://qm.qq.com/cgi-bin/qm/qr?k=aJVwjDvH-Es4MPJQuoO32N0SucK22TE5&jump_from=webapi)
|
||||||
|
|
||||||
- django-vue-admin交流02群(已满):687252418 [点击链接加入群聊](https://qm.qq.com/cgi-bin/qm/qr?k=4jJN4IjWGfxJ8YJXbb_gTsuWjR34WLdc&jump_from=webapi)
|
- django-vue-admin交流02群(已满):687252418 [点击链接加入群聊](https://qm.qq.com/cgi-bin/qm/qr?k=4jJN4IjWGfxJ8YJXbb_gTsuWjR34WLdc&jump_from=webapi)
|
||||||
- django-vue-admin交流03群:442108213 [点击链接加入群聊](http://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=kwmm0yWKN927XnoMRrfpOM0WQFsrhRHX&authKey=8VzzQW73dHSI%2F2LnN%2Fsiffk%2FMRjesIO%2B6j7by1N%2BoizpAExQAjb887tXfWQa7wbT&noverify=0&group_code=442108213)
|
|
||||||
|
- django-vue-admin交流03群:442108213 [点击链接加入群聊](https://qm.qq.com/cgi-bin/qm/qr?k=ESpuF6A1Fcx0XrY4w6CzCvbnjI4kNsa0&jump_from=webapi)
|
||||||
|
|
||||||
- 二维码
|
- 二维码
|
||||||
|
|
||||||
<img src='https://foruda.gitee.com/images/1684571588696924229/2d16437f_7947594.png' width='200'>
|
<img src='https://foruda.gitee.com/images/1685090287886551832/e3afa9e1_5074988.png' width='200'>
|
||||||
|
|
||||||
## 源码地址
|
|
||||||
|
|
||||||
gitee地址(主推):[https://gitee.com/liqianglog/django-vue-admin](https://gitee.com/liqianglog/django-vue-admin)👩👦👦
|
|
||||||
|
|
||||||
github地址:[https://github.com/liqianglog/django-vue-admin](https://github.com/liqianglog/django-vue-admin)👩👦👦
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## 内置功能
|
## 内置功能
|
||||||
|
|
||||||
|
@ -75,13 +81,41 @@ github地址:[https://github.com/liqianglog/django-vue-admin](https://github.c
|
||||||
10. 🗓️操作日志:系统正常操作日志记录和查询;系统异常信息日志记录和查询。
|
10. 🗓️操作日志:系统正常操作日志记录和查询;系统异常信息日志记录和查询。
|
||||||
11. 🔌[插件市场 ](https://bbs.django-vue-admin.com/plugMarket.html):基于Django-Vue-Admin框架开发的应用和插件。
|
11. 🔌[插件市场 ](https://bbs.django-vue-admin.com/plugMarket.html):基于Django-Vue-Admin框架开发的应用和插件。
|
||||||
|
|
||||||
|
## 源码地址
|
||||||
|
|
||||||
|
gitee地址(主推):[https://gitee.com/liqianglog/django-vue-admin](https://gitee.com/liqianglog/django-vue-admin)👩👦👦
|
||||||
|
|
||||||
|
github地址:[https://github.com/liqianglog/django-vue-admin](https://github.com/liqianglog/django-vue-admin)👩👦👦
|
||||||
|
|
||||||
|
| 项目 | Star | 简介 |
|
||||||
|
| ------------------------------------------------------------ | ------------------------------------------------------------ | -------------------------------------------- |
|
||||||
|
| [django-vue-admin](https://gitee.com/liqianglog/django-vue-admin) | [](https://gitee.com/liqianglog/django-vue-admin) [](https://github.com/liqianglog/django-vue-admin) | 基于 Vue2 + element + d2admin + django 实现的管理后台 |
|
||||||
|
| [django-vue3-admin](https://gitee.com/huge-dream/django-vue3-admin) | [](https://gitee.com/huge-dream/django-vue3-admin) [](https://github.com/huge-dream/django-vue3-admin) | 基于 Vue3 + vue-next-admin + fastcrud + django 实现的管理后台 |
|
||||||
|
|
||||||
## 插件市场 🔌
|
## 插件市场 🔌
|
||||||
|
|
||||||
- Celery异步任务:[dvadmin-celery](https://gitee.com/huge-dream/dvadmin-celery)
|
#### [点我查看最新开发进度](https://rgej2wr12o.feishu.cn/base/KevWbAzaEazgD2s8SmKc36PJnwb?table=tblpongo56gp6zN9&view=vewpLA5Hdc) | [插件市场](https://bbs.django-vue-admin.com/plugMarket.html)
|
||||||
- 升级中心后端:[dvadmin-upgrade-center](https://gitee.com/huge-dream/dvadmin-upgrade-center)
|
|
||||||
- 升级中心前端:[dvadmin-upgrade-center-web](https://gitee.com/huge-dream/dvadmin-upgrade-center-web)
|
| 插件名称 | 开发状态 | 简介 |
|
||||||
|
| --------------------------------------------------------- | -------- | ------------------------------------------------------------ |
|
||||||
|
| [dvadmin3-celery 定时任务](https://bbs.django-vue-admin.com/plugMarket/129.html) | 已发布 | 适用dvadmin3可快速使用异步任务,包含在线添加任务、任务记录等 |
|
||||||
|
| [dvadmin-celery 定时任务](https://bbs.django-vue-admin.com/plugMarket/115.html) | 已发布 | 适用dvadmin3可快速使用异步任务,包含在线添加任务、任务记录等 |
|
||||||
|
| [dvadmin-sms 短信服务](https://bbs.django-vue-admin.com/plugMarket/128.html) | 已发布 | 整合各端的短信服务插件 |
|
||||||
|
| [dvadmin-vform 表单设计器](https://bbs.django-vue-admin.com/plugMarket/118.html) | 已发布 | 低代码表单设计器插件 |
|
||||||
|
| [dvadmin-tenants 多租户管理](https://bbs.django-vue-admin.com/plugMarket/124.html) | 已发布 | 多租户的saas模式 |
|
||||||
|
| [dvadmin-third 第三方用户管理](https://bbs.django-vue-admin.com/plugMarket/122.html) | 已发布 | 第三方用户管理插件 |
|
||||||
|
| [dvadmin-ak-sk 加密密钥管理](https://bbs.django-vue-admin.com/plugMarket/120.html) | 已发布 | 用于加密认证字符串来验证认证字符串的密钥 |
|
||||||
|
| [dvadmin-pay 支付插件]() | 已发布 | 适用于dvadmin的支付插件,支持微信支持、支付宝支付 |
|
||||||
|
| [dvadmin-uniapp](https://bbs.django-vue-admin.com/plugMarket/130.html) | 已发布 | 适用于dvadmin的uniapp插件 |
|
||||||
|
| dvadmin-cloud-storage 云存储插件 | 开发中 | 适用各种云存储进行存储插件 |
|
||||||
|
| dvadmin-es 搜索插件 | 开发中 | 适用于es的搜索插件 |
|
||||||
|
| dvadmin-low-code-crud 低代码生成 | 开发中 | 低代码生成插件 |
|
||||||
|
| dvadmin-flow 工作流插件 | 开发中 | 工作流插件 |
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## 准备工作
|
## 准备工作
|
||||||
|
|
||||||
~~~
|
~~~
|
||||||
Python >= 3.8.0 (推荐3.8+版本)
|
Python >= 3.8.0 (推荐3.8+版本)
|
||||||
nodejs >= 14.0 (推荐最新)
|
nodejs >= 14.0 (推荐最新)
|
||||||
|
@ -197,6 +231,8 @@ docker-compose up -d --build
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
|
#商业授权
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -366,14 +366,17 @@ CAPTCHA_CHALLENGE_FUNCT = "captcha.helpers.math_challenge" # 加减乘除验证
|
||||||
# ================================================= #
|
# ================================================= #
|
||||||
|
|
||||||
DEFAULT_AUTO_FIELD = "django.db.models.AutoField"
|
DEFAULT_AUTO_FIELD = "django.db.models.AutoField"
|
||||||
API_LOG_ENABLE = True
|
# 是否启动API日志记录
|
||||||
|
API_LOG_ENABLE = locals().get("API_LOG_ENABLE", True)
|
||||||
|
# API 日志记录的请求方式
|
||||||
|
API_LOG_METHODS = locals().get("API_LOG_METHODS", ["POST", "UPDATE", "DELETE", "PUT"])
|
||||||
# API_LOG_METHODS = 'ALL' # ['POST', 'DELETE']
|
# API_LOG_METHODS = 'ALL' # ['POST', 'DELETE']
|
||||||
API_LOG_METHODS = ["POST", "UPDATE", "DELETE", "PUT"] # ['POST', 'DELETE']
|
# 在操作日志中详细记录的请求模块映射
|
||||||
API_MODEL_MAP = {
|
API_MODEL_MAP = locals().get("API_MODEL_MAP", {
|
||||||
"/token/": "登录模块",
|
"/token/": "登录模块",
|
||||||
"/api/login/": "登录模块",
|
"/api/login/": "登录模块",
|
||||||
"/api/plugins_market/plugins/": "插件市场",
|
"/api/logout/": "登录模块",
|
||||||
}
|
})
|
||||||
|
|
||||||
DJANGO_CELERY_BEAT_TZ_AWARE = False
|
DJANGO_CELERY_BEAT_TZ_AWARE = False
|
||||||
CELERY_TIMEZONE = "Asia/Shanghai" # celery 时区问题
|
CELERY_TIMEZONE = "Asia/Shanghai" # celery 时区问题
|
||||||
|
|
|
@ -39,6 +39,11 @@ DEBUG = True
|
||||||
ENABLE_LOGIN_ANALYSIS_LOG = True
|
ENABLE_LOGIN_ANALYSIS_LOG = True
|
||||||
# 登录接口 /api/token/ 是否需要验证码认证,用于测试,正式环境建议取消
|
# 登录接口 /api/token/ 是否需要验证码认证,用于测试,正式环境建议取消
|
||||||
LOGIN_NO_CAPTCHA_AUTH = True
|
LOGIN_NO_CAPTCHA_AUTH = True
|
||||||
|
# 是否启动API日志记录
|
||||||
|
API_LOG_ENABLE = locals().get("API_LOG_ENABLE", True)
|
||||||
|
# API 日志记录的请求方式
|
||||||
|
API_LOG_METHODS = locals().get("API_LOG_METHODS", ["POST", "UPDATE", "DELETE", "PUT"])
|
||||||
|
# API_LOG_METHODS = 'ALL' # ['POST', 'DELETE']
|
||||||
# ================================================= #
|
# ================================================= #
|
||||||
# ****************** 其他 配置 ******************* #
|
# ****************** 其他 配置 ******************* #
|
||||||
# ================================================= #
|
# ================================================= #
|
||||||
|
|
|
@ -34,7 +34,7 @@ class Command(BaseCommand):
|
||||||
def serializer_data(self, serializer, query_set: QuerySet):
|
def serializer_data(self, serializer, query_set: QuerySet):
|
||||||
serializer = serializer(query_set, many=True)
|
serializer = serializer(query_set, many=True)
|
||||||
data = json.loads(json.dumps(serializer.data, ensure_ascii=False))
|
data = json.loads(json.dumps(serializer.data, ensure_ascii=False))
|
||||||
with open(os.path.join(BASE_DIR, f'init_{query_set.model._meta.model_name}.json'), 'w') as f:
|
with open(os.path.join(BASE_DIR, f'init_{query_set.model._meta.model_name}.json'), 'w',encoding="utf-8") as f:
|
||||||
json.dump(data, f, indent=4, ensure_ascii=False)
|
json.dump(data, f, indent=4, ensure_ascii=False)
|
||||||
return
|
return
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import hashlib
|
import hashlib
|
||||||
|
|
||||||
from django.contrib.auth.hashers import make_password
|
from django.contrib.auth.hashers import make_password, check_password
|
||||||
from django_restql.fields import DynamicSerializerMethodField
|
from django_restql.fields import DynamicSerializerMethodField
|
||||||
from rest_framework import serializers
|
from rest_framework import serializers
|
||||||
from rest_framework.decorators import action, permission_classes
|
from rest_framework.decorators import action, permission_classes
|
||||||
|
@ -251,9 +251,9 @@ class UserViewSet(CustomModelViewSet):
|
||||||
update_serializer_class = UserUpdateSerializer
|
update_serializer_class = UserUpdateSerializer
|
||||||
# filter_fields = ["name", "username", "gender", "is_active", "dept", "user_type"]
|
# filter_fields = ["name", "username", "gender", "is_active", "dept", "user_type"]
|
||||||
filter_fields = {
|
filter_fields = {
|
||||||
"name": ["exact"],
|
"name": ["icontains"],
|
||||||
"mobile": ["exact"],
|
"mobile": ["icontains"],
|
||||||
"username": ["exact"],
|
"username": ["icontains"],
|
||||||
"gender": ["icontains"],
|
"gender": ["icontains"],
|
||||||
"is_active": ["icontains"],
|
"is_active": ["icontains"],
|
||||||
"dept": ["exact"],
|
"dept": ["exact"],
|
||||||
|
@ -347,10 +347,10 @@ class UserViewSet(CustomModelViewSet):
|
||||||
return ErrorResponse(msg="参数不能为空")
|
return ErrorResponse(msg="参数不能为空")
|
||||||
if new_pwd != new_pwd2:
|
if new_pwd != new_pwd2:
|
||||||
return ErrorResponse(msg="两次密码不匹配")
|
return ErrorResponse(msg="两次密码不匹配")
|
||||||
check_password = request.user.check_password(old_pwd)
|
verify_password = check_password(old_pwd, self.request.user.password)
|
||||||
if not check_password:
|
if not verify_password:
|
||||||
check_password = request.user.check_password(hashlib.md5(old_pwd.encode(encoding='UTF-8')).hexdigest())
|
verify_password = check_password(hashlib.md5(old_pwd.encode(encoding='UTF-8')).hexdigest(), self.request.user.password)
|
||||||
if check_password:
|
if verify_password:
|
||||||
request.user.password = make_password(new_pwd)
|
request.user.password = make_password(new_pwd)
|
||||||
request.user.save()
|
request.user.save()
|
||||||
return DetailResponse(data=None, msg="修改成功")
|
return DetailResponse(data=None, msg="修改成功")
|
||||||
|
|
|
@ -3,8 +3,11 @@ import logging
|
||||||
|
|
||||||
from django.contrib.auth import get_user_model
|
from django.contrib.auth import get_user_model
|
||||||
from django.contrib.auth.backends import ModelBackend
|
from django.contrib.auth.backends import ModelBackend
|
||||||
|
from django.contrib.auth.hashers import check_password
|
||||||
from django.utils import timezone
|
from django.utils import timezone
|
||||||
|
|
||||||
|
from dvadmin.utils.validator import CustomValidationError
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
UserModel = get_user_model()
|
UserModel = get_user_model()
|
||||||
|
|
||||||
|
@ -24,10 +27,13 @@ class CustomBackend(ModelBackend):
|
||||||
except UserModel.DoesNotExist:
|
except UserModel.DoesNotExist:
|
||||||
UserModel().set_password(password)
|
UserModel().set_password(password)
|
||||||
else:
|
else:
|
||||||
check_password = user.check_password(password)
|
verify_password = check_password(password, user.password)
|
||||||
if not check_password:
|
if not verify_password:
|
||||||
check_password = user.check_password(hashlib.md5(password.encode(encoding='UTF-8')).hexdigest())
|
password = hashlib.md5(password.encode(encoding='UTF-8')).hexdigest()
|
||||||
if check_password and self.user_can_authenticate(user):
|
verify_password = check_password(password, user.password)
|
||||||
|
if verify_password:
|
||||||
|
if self.user_can_authenticate(user):
|
||||||
user.last_login = timezone.now()
|
user.last_login = timezone.now()
|
||||||
user.save()
|
user.save()
|
||||||
return user
|
return user
|
||||||
|
raise CustomValidationError("当前用户已被禁用,请联系管理员!")
|
||||||
|
|
|
@ -154,12 +154,14 @@ class CustomDjangoFilterBackend(DjangoFilterBackend):
|
||||||
"~": "icontains",
|
"~": "icontains",
|
||||||
}
|
}
|
||||||
|
|
||||||
def construct_search(self, field_name):
|
def construct_search(self, field_name, lookup_expr=None):
|
||||||
lookup = self.lookup_prefixes.get(field_name[0])
|
lookup = self.lookup_prefixes.get(field_name[0])
|
||||||
if lookup:
|
if lookup:
|
||||||
field_name = field_name[1:]
|
field_name = field_name[1:]
|
||||||
else:
|
else:
|
||||||
lookup = "icontains"
|
lookup = lookup_expr
|
||||||
|
if field_name.endswith(lookup):
|
||||||
|
return field_name
|
||||||
return LOOKUP_SEP.join([field_name, lookup])
|
return LOOKUP_SEP.join([field_name, lookup])
|
||||||
|
|
||||||
def find_filter_lookups(self, orm_lookups, search_term_key):
|
def find_filter_lookups(self, orm_lookups, search_term_key):
|
||||||
|
@ -239,7 +241,10 @@ class CustomDjangoFilterBackend(DjangoFilterBackend):
|
||||||
# warn if the field doesn't exist.
|
# warn if the field doesn't exist.
|
||||||
if field is None:
|
if field is None:
|
||||||
undefined.append(field_name)
|
undefined.append(field_name)
|
||||||
|
# 更新默认字符串搜索为模糊搜索
|
||||||
|
if isinstance(field, (models.CharField)) and filterset_fields == '__all__' and lookups == [
|
||||||
|
'exact']:
|
||||||
|
lookups = ['icontains']
|
||||||
for lookup_expr in lookups:
|
for lookup_expr in lookups:
|
||||||
filter_name = cls.get_filter_name(field_name, lookup_expr)
|
filter_name = cls.get_filter_name(field_name, lookup_expr)
|
||||||
|
|
||||||
|
@ -288,7 +293,7 @@ class CustomDjangoFilterBackend(DjangoFilterBackend):
|
||||||
for search_field in filterset.filters:
|
for search_field in filterset.filters:
|
||||||
if isinstance(filterset.filters[search_field], CharFilter):
|
if isinstance(filterset.filters[search_field], CharFilter):
|
||||||
orm_lookups.append(
|
orm_lookups.append(
|
||||||
self.construct_search(six.text_type(search_field))
|
self.construct_search(six.text_type(search_field), filterset.filters[search_field].lookup_expr)
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
orm_lookups.append(search_field)
|
orm_lookups.append(search_field)
|
||||||
|
|
|
@ -21,9 +21,9 @@ def import_to_data(file_url, field_data, m2m_fields=None):
|
||||||
file_path_dir = os.path.join(settings.BASE_DIR, file_url)
|
file_path_dir = os.path.join(settings.BASE_DIR, file_url)
|
||||||
workbook = openpyxl.load_workbook(file_path_dir)
|
workbook = openpyxl.load_workbook(file_path_dir)
|
||||||
table = workbook[workbook.sheetnames[0]]
|
table = workbook[workbook.sheetnames[0]]
|
||||||
theader = tuple(table.values)[0] #Excel的表头
|
theader = tuple(table.values)[0] # Excel的表头
|
||||||
is_update = '更新主键(勿改)' in theader #是否导入更新
|
is_update = '更新主键(勿改)' in theader # 是否导入更新
|
||||||
if is_update is False: #不是更新时,删除id列
|
if is_update is False: # 不是更新时,删除id列
|
||||||
field_data.pop('id')
|
field_data.pop('id')
|
||||||
# 获取参数映射
|
# 获取参数映射
|
||||||
validation_data_dict = {}
|
validation_data_dict = {}
|
||||||
|
@ -35,9 +35,10 @@ def import_to_data(file_url, field_data, m2m_fields=None):
|
||||||
for k, v in choices.get("data").items():
|
for k, v in choices.get("data").items():
|
||||||
data_dict[k] = v
|
data_dict[k] = v
|
||||||
elif choices.get("queryset") and choices.get("values_name"):
|
elif choices.get("queryset") and choices.get("values_name"):
|
||||||
data_list = choices.get("queryset").values(choices.get("values_name"), "id")
|
data_list = choices.get("queryset").values(choices.get("values_name"),
|
||||||
|
choices.get("values_value", "id"))
|
||||||
for ele in data_list:
|
for ele in data_list:
|
||||||
data_dict[ele.get(choices.get("values_name"))] = ele.get("id")
|
data_dict[ele.get(choices.get("values_name"))] = ele.get(choices.get("values_value", "id"))
|
||||||
else:
|
else:
|
||||||
continue
|
continue
|
||||||
validation_data_dict[key] = data_dict
|
validation_data_dict[key] = data_dict
|
||||||
|
@ -53,12 +54,11 @@ def import_to_data(file_url, field_data, m2m_fields=None):
|
||||||
values = items[1]
|
values = items[1]
|
||||||
value_type = 'str'
|
value_type = 'str'
|
||||||
if isinstance(values, dict):
|
if isinstance(values, dict):
|
||||||
value_type = values.get('type','str')
|
value_type = values.get('type', 'str')
|
||||||
cell_value = table.cell(row=row + 1, column=index + 2).value
|
cell_value = table.cell(row=row + 1, column=index + 2).value
|
||||||
if cell_value is None or cell_value=='':
|
if cell_value is None or cell_value == '':
|
||||||
continue
|
continue
|
||||||
elif value_type == 'date':
|
elif value_type == 'date':
|
||||||
print(61, datetime.strptime(str(cell_value), '%Y-%m-%d %H:%M:%S').date())
|
|
||||||
try:
|
try:
|
||||||
cell_value = datetime.strptime(str(cell_value), '%Y-%m-%d %H:%M:%S').date()
|
cell_value = datetime.strptime(str(cell_value), '%Y-%m-%d %H:%M:%S').date()
|
||||||
except:
|
except:
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
|
from types import FunctionType, MethodType
|
||||||
from urllib.parse import quote
|
from urllib.parse import quote
|
||||||
|
|
||||||
from django.db import transaction
|
from django.db import transaction
|
||||||
|
@ -68,6 +69,8 @@ class ImportSerializerMixin:
|
||||||
:return:
|
:return:
|
||||||
"""
|
"""
|
||||||
assert self.import_field_dict, "'%s' 请配置对应的导出模板字段。" % self.__class__.__name__
|
assert self.import_field_dict, "'%s' 请配置对应的导出模板字段。" % self.__class__.__name__
|
||||||
|
if isinstance(self.import_field_dict, MethodType) or isinstance(self.import_field_dict, FunctionType):
|
||||||
|
self.import_field_dict = self.import_field_dict()
|
||||||
# 导出模板
|
# 导出模板
|
||||||
if request.method == "GET":
|
if request.method == "GET":
|
||||||
# 示例数据
|
# 示例数据
|
||||||
|
@ -160,6 +163,8 @@ class ImportSerializerMixin:
|
||||||
assert self.import_field_dict, "'%s' 请配置对应的导入模板字段。" % self.__class__.__name__
|
assert self.import_field_dict, "'%s' 请配置对应的导入模板字段。" % self.__class__.__name__
|
||||||
assert self.import_serializer_class, "'%s' 请配置对应的导入序列化器。" % self.__class__.__name__
|
assert self.import_serializer_class, "'%s' 请配置对应的导入序列化器。" % self.__class__.__name__
|
||||||
data = self.import_serializer_class(queryset, many=True, request=request).data
|
data = self.import_serializer_class(queryset, many=True, request=request).data
|
||||||
|
if isinstance(self.import_field_dict, MethodType) or isinstance(self.import_field_dict, FunctionType):
|
||||||
|
self.import_field_dict = self.import_field_dict()
|
||||||
# 导出excel 表
|
# 导出excel 表
|
||||||
response = HttpResponse(content_type="application/msexcel")
|
response = HttpResponse(content_type="application/msexcel")
|
||||||
response["Access-Control-Expose-Headers"] = f"Content-Disposition"
|
response["Access-Control-Expose-Headers"] = f"Content-Disposition"
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "django-vue-admin",
|
"name": "django-vue-admin",
|
||||||
"version": "2.1.3",
|
"version": "2.1.4",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"serve": "vue-cli-service serve --open",
|
"serve": "vue-cli-service serve --open",
|
||||||
"start": "npm run serve",
|
"start": "npm run serve",
|
||||||
|
|
|
@ -104,7 +104,7 @@ export default {
|
||||||
},
|
},
|
||||||
grid: {
|
grid: {
|
||||||
top: 40,
|
top: 40,
|
||||||
left: 40,
|
left: 50,
|
||||||
right: 65,
|
right: 65,
|
||||||
bottom: 75
|
bottom: 75
|
||||||
},
|
},
|
||||||
|
|
|
@ -95,7 +95,7 @@ export default {
|
||||||
},
|
},
|
||||||
grid: {
|
grid: {
|
||||||
top: 40,
|
top: 40,
|
||||||
left: 40,
|
left: 50,
|
||||||
right: 65,
|
right: 65,
|
||||||
bottom: 60
|
bottom: 60
|
||||||
},
|
},
|
||||||
|
|
|
@ -98,7 +98,7 @@ export default {
|
||||||
},
|
},
|
||||||
grid: {
|
grid: {
|
||||||
top: 40,
|
top: 40,
|
||||||
left: 40,
|
left: 50,
|
||||||
right: 65,
|
right: 65,
|
||||||
bottom: 60
|
bottom: 60
|
||||||
},
|
},
|
||||||
|
|
|
@ -61,8 +61,8 @@ export function ResetPwd (obj) {
|
||||||
*/
|
*/
|
||||||
export function exportData (params) {
|
export function exportData (params) {
|
||||||
return downloadFile({
|
return downloadFile({
|
||||||
url: urlPrefix + 'export/',
|
url: urlPrefix + 'export_data/',
|
||||||
params: params,
|
params: params,
|
||||||
method: 'post'
|
method: 'get'
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue