所以这种扩展更详细地说明了@Nathan 的建议。
拿一个
首先,您可以在您认为用户会点击新闻通讯订阅链接的每个模板中发布订阅表单。表单是隐藏的,一旦覆盖触发它就会显示出来。
{# newsletter_subscribe_request_form_overlay.html #}
{% if newsletter_subscribe_request_form %}
<div id="newsletter_subscribe_request_form_overlay" class="simple_overlay">
<form action="{% url newsletter_subscribe_request %}" method="POST">
{{ newsletter_subscribe_request_form.as_p }}
<input type="submit" value="Subscribe to the newsletter" />
{% csrf_token %}
</form>
</div>
{% endif %}
{# now, in the templates where the overlay action link will be present #}
{# ...at the very bottom, just before the `BODY` element closing tag #}
{% include 'newsletter_subscribe_request_form_overlay.html' %}
好的,所以这基本上可以让您将隐藏的订阅表单放置在您希望通过覆盖显示它的任何页面上。现在剩下的是将newsletter_subscribe_request_form 添加到模板上下文中。您可以通过更新视图以将表单添加到上下文中来做到这一点,或者您可以创建一个上下文处理器。就个人而言,我更喜欢上下文处理器:
from newsletter.models import Subscription
from newsletter.forms import SubscribeRequestForm
def newsletter_subscribe_request_form_overlay(request):
'''
Inserts a newsletter subscribe request form into the context
for every user that's not yet subscribed.
'''
try:
Subscription.objects.get(user=request.user)
# object exists, user is already subscribed
return {}
except Subscription.DoesNotExist:
# object doesn't exist, push the form to the context
return {'newsletter_subscribe_request_form': SubscribeRequestForm()}
except:
# something unexpected happened, or I messed up
return {}
这样就结束了这种方法。这个非常简单,因为它只包括编写一个简单的模板,将其包含在其他模板中,然后有一个上下文处理器,它将表单推送到未订阅用户的模板上下文中。
另一方面,根据您的团队或个人喜好,这可能太神奇了,无法处理。除非您在某处记录该方法,否则上下文中的newsletter_subscribe_request_form 来自哪里会有点不直观(视图?;上下文处理器之一?),您可能还必须通过一个大模板继承线来找出包含newsletter_subscribe_request_form_overlay.html 的位置。更不用说,您对每个请求都进行了额外的数据库查询。
不过,这样做的好处是,如果用户已订阅,您还可以将取消订阅表单添加到上下文中,并且根据两者中的哪一个存在,您可以动态更改“订阅”和“订阅”之间的链接标题“退订”,这将是您可以给予用户的小福利之一。
拿两个
第二种方法是创建一个简单的CreateView,您可以通过 Ajax 调用获取它并以交互方式在叠加层中显示内容。
from django.views.generic.edit import CreateView
from newsletter.forms import SubscribeRequestForm
from django.http import HttpResponseBadRequest
class AjaxSubscriptionRequestView(CreateView):
''''
A simple subscription create view that returns a
subscription form in the response for Ajax calls
''''
http_method_names = ['get',]
form_class = SubscribeRequestForm
template_name = 'newsletter_subscribe_request_form_overlay.html'
def get_initial(self):
return {'user': self.request.user}
def get(self, request, *args, **kwargs):
if not request.is_ajax():
return HttpResponseBadRequest()
else:
return super(AjaxSubscriptionRequestView, self).get(request,
*args, **kwargs)
所以我们使用与第一个示例相同的模板,所以我们只是在响应中返回表单。现在只需获取表单并在检索到它后将其显示在叠加层中。
<script type="text/javascript">
function newsletterSubscribeRequestFormOverlay(eventObject) {
eventObject.preventDefault();
$.ajax({
url: "{% url ajax-subscription-request %}",
cache: false,
success: function(html){
$('body').append(html);
$('.simple_overlay').overlay();
}
});
}
</script>
<a href="{% url newsletter_subscribe_request %}"
onclick="javascript: newsletterSubscribeRequestFormOverlay(event);">
Subscribe to our newsletter
</a>
当然,这需要一些额外的吐槽和润色。您可以使用微调器显示叠加层,直到您收到表单 HTML 的响应,以便在用户单击订阅链接时为他们提供某种形式的反馈。