Django实现前端按钮调用带不同参数的同一视图函数
解决方案
核心思路
绝对不能让前端直接传递敏感凭证(如密码),所有敏感信息必须留在后端。我们通过让前端传递服务器标识(如fu/fv/usv),后端根据标识从settings中读取对应凭证,实现安全的多服务器同步。
1. 重构视图逻辑
修改原视图,移除直接接收凭证的参数,改用服务器标识匹配后端存储的凭证,并添加异常处理和重复数据校验:
from django.conf import settings from django.contrib import messages from django.shortcuts import redirect import imaplib import email from email.header import make_header, decode_header from .models import EmailMarketing def get_emails(request, server_key): # 映射服务器标识到对应凭证 server_configs = { 'fu': { 'host': settings.FU_HOST, 'username': settings.FU_USERNAME, 'password': settings.FU_PASSWORD }, 'fv': { 'host': settings.FV_HOST, 'username': settings.FV_USERNAME, 'password': settings.FV_PASSWORD }, 'usv': { 'host': settings.USV_HOST, 'username': settings.USV_USERNAME, 'password': settings.USV_PASSWORD } } # 验证标识合法性 if server_key not in server_configs: messages.error(request, '无效的服务器选择') return redirect('subscribers') config = server_configs[server_key] try: # 连接IMAP服务器 m = imaplib.IMAP4_SSL(config['host'], 993) m.login(config['username'], config['password']) m.select('INBOX') # 搜索并处理邮件 result, data = m.uid('search', None, "ALL") if result == 'OK': for num in data[0].split(): result, data = m.uid('fetch', num, '(RFC822)') if result == 'OK': email_message_raw = email.message_from_bytes(data[0][1]) email_from = str(make_header(decode_header(email_message_raw['From']))) # 提取邮箱地址 email_addr = email_from.replace('<', '>').split('>') email_address = email_addr[1].strip() if len(email_addr) > 1 else email_addr[0].strip() # 避免重复存储 if not EmailMarketing.objects.filter(email_address=email_address, mail_server=server_key.upper()).exists(): EmailMarketing.objects.create(email_address=email_address, mail_server=server_key.upper()) m.close() m.logout() messages.success(request, f'已成功同步{server_key.upper()}服务器的订阅列表') except Exception as e: messages.error(request, f'同步失败: {str(e)}') # 异常时确保连接关闭 try: m.close() m.logout() except: pass return redirect('subscribers')
2. 配置URL路由
在应用的urls.py中添加带服务器标识参数的路由:
from django.urls import path from . import views urlpatterns = [ # 其他路由... path('sync-emails/<str:server_key>/', views.get_emails, name='sync_emails'), ]
3. 前端添加触发按钮
在模板(如subscribers.html)中创建三个独立表单,每个表单对应一个服务器标识,通过POST请求触发同步:
<form method="POST" action="{% url 'sync_emails' 'fu' %}"> {% csrf_token %} <button type="submit">同步FU服务器邮件</button> </form> <form method="POST" action="{% url 'sync_emails' 'fv' %}"> {% csrf_token %} <button type="submit">同步FV服务器邮件</button> </form> <form method="POST" action="{% url 'sync_emails' 'usv' %}"> {% csrf_token %} <button type="submit">同步USV服务器邮件</button> </form>
4. 环境变量配置
确保通过python-dotenv加载.env文件中的凭证:
- 安装依赖:
pip install python-dotenv - 在项目根目录的
settings.py开头添加:
from dotenv import load_dotenv import os load_dotenv() # 加载.env文件
- 在
.env文件中存储凭证(务必将.env加入.gitignore):
FU_HOST=你的FU_IMAP服务器地址 FU_USERNAME=你的FU邮箱账号 FU_PASSWORD=你的FU邮箱密码 FV_HOST=你的FV_IMAP服务器地址 FV_USERNAME=你的FV邮箱账号 FV_PASSWORD=你的FV邮箱密码 USV_HOST=你的USV_IMAP服务器地址 USV_USERNAME=你的USV邮箱账号 USV_PASSWORD=你的USV邮箱密码
安全补充建议
- 给视图添加权限控制:比如用
@login_required和@user_passes_test装饰器,限制仅管理员能触发同步 - 可以给同步操作添加异步任务(如Celery),避免长时间阻塞请求
内容的提问来源于stack exchange,提问作者chr0sy
相关产品推荐
相关产品推荐

