diff --git a/README.md b/README.md
index c964844..82f4a4a 100644
--- a/README.md
+++ b/README.md
@@ -58,7 +58,7 @@ pip install --no-cache-dir -r requirements.txt -i https://pypi.mirrors.ustc.edu.
```shell
1、开放计划任务配置
- 2、支持签到失败重试(忽略cookie失效站点),建议失败重试时间设置5分钟以上
+ 2、支持签到失败重试(忽略cookie失效站点),建议失败重试时间设置5分钟以上(由于sqlite单进程模式,因此重试和签到不要放在同一个分钟或小时,建议差距2分钟以上)
```
# v2.0 说明
@@ -151,6 +151,15 @@ root 数据库用户名
3306 数据库端口
pthelper 数据库名称
```
+#sqlite迁移到mysql步骤
+```shell
+1、系统管理---》备份恢复,点击备份
+2、关闭docker
+3、修改conf下的env.prod,配置你使用的mysql,并创建你配置的数据库
+4、启动docker
+5、系统管理---》备份恢复,选择要恢复的文件,然后点击恢复
+6、刷新页面,重新登录系统
+```
## 感谢
diff --git a/apps/common/templates/common/backup.html b/apps/common/templates/common/backup.html
index 89083b4..99dd577 100644
--- a/apps/common/templates/common/backup.html
+++ b/apps/common/templates/common/backup.html
@@ -1,74 +1,136 @@
-
+
+
+
+
\ No newline at end of file
diff --git a/apps/common/urls/views_urls.py b/apps/common/urls/views_urls.py
index c0a349e..fcc0b1a 100644
--- a/apps/common/urls/views_urls.py
+++ b/apps/common/urls/views_urls.py
@@ -13,6 +13,8 @@ urlpatterns = [
path('backup', views.BackupView.as_view()),
path('backup/export', views_request.backupExport),
path('backup/import', views_request.backupImport),
+ path('backup/list', views_request.backupList),
+ path('backup/del', views_request.backupDel),
#补签
path('signagain', views_request.signAgain),
path('signcheck', views_request.signCheck),
diff --git a/apps/common/views.py b/apps/common/views.py
index 75d3449..6b8d3e5 100644
--- a/apps/common/views.py
+++ b/apps/common/views.py
@@ -5,68 +5,6 @@ from django.http import JsonResponse
from django.conf import settings
from git.repo import Repo
-# Create your views here.
-#------------------------------
-#class BaiDuOcrView(LoginRequiredMixin,TemplateView):
- #"""
- #百度OCR配置
- #"""
- #template_name = 'common/baidu_ocr.html'
-
- ##显示添加模板
- #def get(self, request, *args, **kwargs):
- #"""
- #得到
- #"""
-
- #return super(BaiDuOcrView, self).get(request, *args, **kwargs)
-
- ##显示编辑模板
- #def get_context_data(self, **kwargs):
-
- ##获取记录
- #orm_count = BaiDuOcr.objects.count()
- #if orm_count == 0:
-
- #context = {}
- #else:
- ##获取一条数据
- #ormdata = BaiDuOcr.objects.first()
- #context = {
- #'id': ormdata.id,
- #'app_id': ormdata.app_id,
- #'app_key': ormdata.app_key,
- #'secret_key': ormdata.secret_key,
- #}
- #kwargs.update(context)
- #return super(BaiDuOcrView, self).get_context_data(**kwargs)
-
- ##数据提交接收方法
- #def post(self, request, *args, **kwargs):
- #"""
- #数据提交
- #"""
- #_id = request.POST.get('id','')
- #app_id = request.POST.get("app_id").strip()
- #app_key = request.POST.get("app_key").strip()
- #secret_key = request.POST.get("secret_key").strip()
-
- #if _id == '':
- #ormdata = BaiDuOcr.objects.create(app_id=app_id,
- #app_key=app_key,
- #secret_key=secret_key,
- #)
- #else:
- #ormdata = BaiDuOcr.objects.get(id=_id)
- #ormdata.app_id = app_id
- #ormdata.app_key = app_key
- #ormdata.secret_key = secret_key
-
- #ormdata.save()
-
- #response_data={"code":1,"msg":"添加成功"}
-
- #return JsonResponse(response_data)
class BackupView(LoginRequiredMixin,TemplateView):
"""
diff --git a/apps/common/views_request.py b/apps/common/views_request.py
index 6eefce0..e66d2c5 100644
--- a/apps/common/views_request.py
+++ b/apps/common/views_request.py
@@ -7,7 +7,8 @@ from django.core.management import call_command
import logging
import tempfile
import os
-import shutil
+from datetime import datetime
+import simplejson as json
from sites.models import SiteInfo,SiteConfig
from cron.models import Log
@@ -22,23 +23,27 @@ def backupExport(request):
logger = logging.getLogger('django')
if request.method == "POST":
- action = request.POST.get('action','')
- backup_file = os.path.join(settings.BACKUP_DIR,'pthelper.json')
- logger.info("Starting backup process.")
+ #backup_file = os.path.join(settings.BACKUP_DIR,'pthelper.json')
+ backup_file = os.path.join(settings.BACKUP_DIR,'export_{}.json'.format(datetime.now().strftime("%Y-%m-%d_%H-%M")))
+ logger.info("开始导出数据.")
with tempfile.TemporaryDirectory() as d:
dump_path = os.path.join(d, 'dump.json')
- logger.info("Starting data dump...")
+
#call_command('dumpdata', '--exclude','cron.Log',natural_foreign=True, output=dump_path)
- call_command('dumpdata', exclude=['cron.Log'], natural_foreign=True, output=dump_path)
+ #call_command('dumpdata', exclude=['cron.Log'], natural_foreign=True, output=dump_path, format='json', indent=4)
+ call_command('dumpdata', exclude=['authtoken.Token'], natural_foreign=True, natural_primary=True, output=dump_path, format='json', indent=4)
- logger.info("Data dumped.")
- logger.info("Copying BACKUP_DIR to %s...", backup_file)
- #shutil.copytree(settings.MEDIA_ROOT, os.path.join(d, 'media'))
- shutil.copyfile(dump_path, backup_file)
-
- logger.info('Copy done.')
+ logger.info("备份完成.")
+ logger.info("开始转换备份文件 %s...", backup_file)
+ #将乱码转换成中文
+ with open(dump_path) as f:
+ data = json.load(f)
+ with open(backup_file, 'w', encoding='utf-8') as f:
+ json.dump(data, f, ensure_ascii=False, indent=4)
+
+ logger.info('转换完成.')
#backup_path = os.path.join(settings.BACKUP_DIR, datetime.date.today().strftime("%Y-%m-%d.zip"))
#with zipfile.ZipFile(backup_path, mode='w') as backup_zip:
#for root, dirs, files in os.walk(d):
@@ -49,7 +54,7 @@ def backupExport(request):
#arcname=os.path.relpath(filepath, d))
#logger.info("{} created.".format(backup_path))
- response_data={"code":0,"msg":"ok" }
+ response_data={"code":1,"msg":"备份完成" }
return JsonResponse(response_data)
@@ -59,17 +64,57 @@ def backupImport(request):
"""
数据恢复
"""
- logger = logging.getLogger('django')
if request.method == "POST":
- action = request.POST.get('action','')
- backup_file = os.path.join(settings.BACKUP_DIR,'pthelper.json')
- logger.info("Starting load process.")
-
- call_command('loaddata', backup_file)
+ name = request.POST.get('name')
+ backup_file = os.path.join(settings.BACKUP_DIR, name)
+ try:
+
+ call_command('loaddata', backup_file)
+
+ response_data={"code":1,"msg":"恢复完成" }
+ except Exception as e:
+ response_data={"code":0,"msg":"恢复失败" + str(e) }
+
+ return JsonResponse(response_data)
+
+#==================
+@login_required
+def backupList(request):
+ """
+ 列出备份数据
+ """
+ data = {}
+ data['code'] = 0
+ data['msg'] = ""
+ data['data'] = []
+
+ for file_name in os.listdir(settings.BACKUP_DIR):
+ data['data'].append({"name":file_name,
+ "url": "/backups/" + file_name
+ })
+
+ return JsonResponse(data)
+
+#==================
+@login_required
+def backupDel(request):
+ """
+ 删除备份数据
+ """
+ name = request.POST.get('name')
+ backup_file = os.path.join(settings.BACKUP_DIR, name)
+ try:
+ os.remove(backup_file)
+ response_data={"code":1,"msg":"删除成功" }
+ except Exception as e:
+ response_data={"code":0,"msg":"删除失败" + str(e) }
+
+ return JsonResponse(response_data)
+
#==================
@login_required
def signAgain(request):
diff --git a/apps/rss/migrations/0017_config_name_alter_config_url.py b/apps/rss/migrations/0017_config_name_alter_config_url.py
new file mode 100644
index 0000000..c7d7824
--- /dev/null
+++ b/apps/rss/migrations/0017_config_name_alter_config_url.py
@@ -0,0 +1,23 @@
+# Generated by Django 4.1 on 2022-09-22 15:02
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('rss', '0016_rule_is_paused'),
+ ]
+
+ operations = [
+ migrations.AddField(
+ model_name='config',
+ name='name',
+ field=models.CharField(max_length=50, null=True, verbose_name='自定义配置名称'),
+ ),
+ migrations.AlterField(
+ model_name='config',
+ name='url',
+ field=models.URLField(blank=True, max_length=350, unique=True, verbose_name='RSS地址'),
+ ),
+ ]
diff --git a/apps/rss/models.py b/apps/rss/models.py
index edbef1e..7ffb785 100644
--- a/apps/rss/models.py
+++ b/apps/rss/models.py
@@ -27,7 +27,8 @@ class FilmType(models.Model):
class Config(models.Model):
"""RSS配置"""
- url = models.URLField('RSS地址', blank=True, max_length=350)
+ name = models.CharField('自定义配置名称', max_length=50, null=True)
+ url = models.URLField('RSS地址', blank=True, max_length=350, unique=True)
#site_name = models.CharField('网站名简称,英文', max_length=50, unique=True)
#site_name_cn = models.CharField('网站名简称,中文', max_length=50, unique=True)
#on_update 和 on_delete 后面可以跟的词语有四个
diff --git a/apps/rss/templates/rss/rssconfig.html b/apps/rss/templates/rss/rssconfig.html
index 21f231c..56d77f5 100644
--- a/apps/rss/templates/rss/rssconfig.html
+++ b/apps/rss/templates/rss/rssconfig.html
@@ -62,6 +62,7 @@
cols: [[
{ type: 'checkbox' },
{ field: 'id', title: 'ID', hide: true },
+ { field: 'name', title: '配置名', width: 200 },
{ field: 'site_name', sort: true, title: '站点', width: 180 },
{ field: 'url', sort: true, title: 'RSS地址' },
{ align: 'center', toolbar: '#rssconfigTableBar', title: '操作', width: 150 }
diff --git a/apps/rss/templates/rss/rssconfigadd.html b/apps/rss/templates/rss/rssconfigadd.html
index c291fe0..1a6d5d3 100644
--- a/apps/rss/templates/rss/rssconfigadd.html
+++ b/apps/rss/templates/rss/rssconfigadd.html
@@ -1,6 +1,13 @@