You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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文件中的凭证:

  1. 安装依赖:pip install python-dotenv
  2. 在项目根目录的settings.py开头添加:
from dotenv import load_dotenv
import os

load_dotenv()  # 加载.env文件
  1. 在.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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.10 05:20:41