How to call django template in order to use it through Jquery?
I've installed the django-newsletter application, and customized the subscribing form. But, right now, I'd like to print it through a Jquery Overlay, instead of a flatpage containing that form. Problem is I don't know how to include this flatpages elements into ev开发者_如何学JAVAery page where the link calling the overlay will be present; and I don't know which approach would be the most performant.
Please light my way :) Thank you!
Create a Django view which renders just the HTML for the form using your preferred template. Then use $.ajax() with dataType: "html" to get the code for the form for use in your overlay.
So this kind of expands in more detail what @Nathan suggested.
Take one
First, you can publish the subscription form in every template where you think the user will click the newsletter subscription link. The form is hidden and will be presented once overlay triggers it for display.
{# 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' %}
Ok, so this would basically allow you to put a hidden subscription form on any page where you'd like to present it with the overlay. What's left now is to add the newsletter_subscribe_request_form
to the template context. You can do this by either updating the views to add the form to the context, or you could create a context processor. Personally, I'd prefer the context processor:
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 {}
So that about wraps up this approach. This one is pretty simple since it only includes writing a simple template, including it in other templates and then having a context processor that will push the form into the template context for unsubscribed users.
The flipside is that, depending on your team or personal preferences, this could be too much magic to handle. Unless you document the approach somewhere, it's going to be a bit unintuitive where does newsletter_subscribe_request_form
in the context come from (the view?; one of the context processors?) and you may also have to go through a big template inheritance line to figure out where newsletter_subscribe_request_form_overlay.html
was included. Not to mention, your doing an additional database query per request.
What this is great for, though, is that you can also add the unsubscribe form to the context if the user is subscribed, and depending which of the two is present, you could dynamically change the link titles between "Subscribe" and "Unsubscribe", which would be one of those small boons you can give to your users.
Take two
The second approach is to create a simple CreateView
that you could fetch via an Ajax call and present the content in the overlay interactively.
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)
So we're using the same template as in the first example, so we're just returning the form in the response. Now it's just a matter of fetching the form and presenting it in an overlay once it's retrieved.
<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>
Of course, this would need some additional spit and polish. You could present the overlay with a spinner until you get the response with the form HTML, to provide users with some form of feedback when they click the subscription link.
Personally I'd also prefer doing it in ajax, but just for future reference, if you want to include html or variables in every request, you can do that in context processors, and to include subtemplates there's an include tag, which you could use in a base template.
http://docs.djangoproject.com/en/dev/ref/templates/api/#writing-your-own-context-processors
http://docs.djangoproject.com/en/dev/ref/templates/builtins/?from=olddocs#include
精彩评论