Django未认证时显示登录弹窗而非跳转页面实现咨询
实现Django Allauth登录弹窗替代页面跳转
1. 修改后端视图逻辑
不再直接重定向到登录页,而是返回当前页面并传递弹窗触发标记,同时保留用户已输入的表单数据:
from django.shortcuts import render, redirect from allauth.account.forms import LoginForm from .forms import ContactEntryForm from .models import ContactEntry def contact_view(request): # 初始化表单,优先从session获取之前输入的数据 contact_form_data = request.session.get('contact_form_data', {}) contact_entry_form = ContactEntryForm(initial=contact_form_data) # 清除session中的表单数据,避免重复填充 request.session.pop('contact_form_data', None) if request.user.is_authenticated: if request.method == "POST": contact_entry_form = ContactEntryForm(request.POST) if contact_entry_form.is_valid(): ContactEntry.objects.create(**contact_entry_form.cleaned_data) return redirect("mainpage") else: if request.method == "POST": # 保存用户输入的表单数据到session request.session['contact_form_data'] = request.POST # 添加全局错误提示 contact_entry_form.add_error(None, "请先登录后提交表单") # 标记需要显示登录弹窗 show_login_modal = True else: show_login_modal = False # 传递登录表单和弹窗标记到模板 return render(request, "contact.html", { "contact_entry_form": contact_entry_form, "show_login_modal": show_login_modal, "login_form": LoginForm() })
2. 前端添加登录模态框
以Bootstrap 5为例,在联系页面模板中嵌入登录弹窗,保留Allauth的登录表单逻辑:
{% load crispy_forms_tags %} <!-- 可选,用于美化表单 --> {% load account %} <!-- 联系表单 --> <form id="contactForm" method="post"> {% csrf_token %} {{ contact_entry_form|crispy }} {% if contact_entry_form.non_field_errors %} <div class="alert alert-danger"> {{ contact_entry_form.non_field_errors.0 }} </div> {% endif %} <button type="submit" class="btn btn-primary">提交</button> </form> <!-- 登录弹窗 --> <div class="modal fade" id="loginModal" tabindex="-1" aria-labelledby="loginModalLabel" aria-hidden="true"> <div class="modal-dialog"> <div class="modal-content"> <div class="modal-header"> <h5 class="modal-title" id="loginModalLabel">用户登录</h5> <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button> </div> <div class="modal-body"> {% url 'account_login' as login_url %} <form id="loginForm" method="post" action="{{ login_url }}"> {% csrf_token %} <!-- 传递next参数,登录后返回当前页面 --> <input type="hidden" name="next" value="{{ request.path }}"> {{ login_form|crispy }} <!-- 登录错误提示 --> {% if form.errors %} <div class="alert alert-danger mt-2"> 用户名或密码错误,请重试 </div> {% endif %} <button type="submit" class="btn btn-primary mt-3">登录</button> </form> <div class="mt-3"> <a href="{% url 'account_signup' %}">还没有账号?立即注册</a> <a href="{% url 'account_reset_password' %}" class="ms-3">忘记密码?</a> </div> </div> </div> </div> </div> <!-- 触发弹窗的JS --> <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script> <script> document.addEventListener('DOMContentLoaded', function() { const loginModal = new bootstrap.Modal(document.getElementById('loginModal')); // 如果后端标记需要显示弹窗,则触发 {% if show_login_modal %} loginModal.show(); {% endif %} }); </script>
3. 优化体验(可选:AJAX无刷新提交)
如果想避免页面跳转,实现无刷新提交,可以修改表单提交逻辑:
后端视图调整
添加AJAX请求判断:
from django.http import JsonResponse from django.urls import reverse def contact_view(request): # ... 其他代码不变 ... if request.user.is_authenticated: if request.method == "POST": contact_entry_form = ContactEntryForm(request.POST) if contact_entry_form.is_valid(): ContactEntry.objects.create(**contact_entry_form.cleaned_data) if request.headers.get('X-Requested-With') == 'XMLHttpRequest': return JsonResponse({'success': True, 'redirect_url': reverse('mainpage')}) return redirect("mainpage") else: if request.method == "POST": if request.headers.get('X-Requested-With') == 'XMLHttpRequest': return JsonResponse({'success': False, 'need_login': True}) # ... 其他代码不变 ... # ... 其他代码不变 ...
前端JS修改
<script> document.addEventListener('DOMContentLoaded', function() { const contactForm = document.getElementById('contactForm'); const loginModal = new bootstrap.Modal(document.getElementById('loginModal')); // AJAX提交联系表单 contactForm.addEventListener('submit', function(e) { e.preventDefault(); const formData = new FormData(this); fetch(this.action, { method: 'POST', body: formData, headers: { 'X-Requested-With': 'XMLHttpRequest' } }) .then(response => response.json()) .then(data => { if (data.success) { window.location.href = data.redirect_url; } else if (data.need_login) { loginModal.show(); } }) .catch(err => console.error('提交失败:', err)); }); {% if show_login_modal %} loginModal.show(); {% endif %} }); </script>
这样用户未登录提交表单时,会直接弹出登录弹窗,登录成功后回到当前页面,表单数据已自动填充,无需重新输入。
内容的提问来源于stack exchange,提问作者penk
相关产品推荐
相关产品推荐

