Is it considered correct/ are there any pitfalls in returning partial templates to ajax POST requests?
For example:
if request.is_ajax:
# response is just the form
return render(request, 'contact/fields.html', {'form':form})
The most typical approach is returning JSON and then contructing whatever HTML you need client-side from the JSON data. However, it could be argued that this is mixing presentation with behavior and it would be better to clearly separate out the HTML.
On the flip-side, returning a block of HTML is about as polar-south of "RESTful" as you can get. In pure REST philosophy, the views should return data in a standard and reusable container (such as JSON or XML). Later if you needed to pull the form into an iOS/Android/WP7/etc. app environment rather than a webpage, the JSON/XML will serve you just as well, whereas the HTML is virtually useless.
I can easily see both arguments, and I don't think one is necessarily more right than the other. Ultimately, I think you just have to do what works best for your app and what "feels right" to you. Think in terms of what is more maintainable and extensible for your particular circumstances.
I have no yet tried this with form POST request but very similarly we return partial HTML to AJAX GET request to do page changes without loading the whole page. I think it would work well for form request as well (we are in fact debating at the moment whether to use this approach on a page with multiple different forms).
I think if done right it is not a bad design pattern. We accomplish this by changing which base template is extended based on whether it was an AJAX call.
A simplified example:
### view
base_template = "base.html"
if request.is_ajax():
base_template = "base-ajax.html"
return render_to_response(request, 'page.html', {'base_template': base_template})
### page.html
{% extends base_template %}
{% block main %}new page content{% endblock %}
### base.html
<html>
<!-- complete html page -->
...
{% block main %}this is what changes per page{% endblock %}
...
</html>
### base-ajax.html
{% block main %}this is what changes per page{% endblock %}
I think most of my ajax return responses return DOM elements and not the entire form.
(an example)
...
person = ''' {1} {2}'''.format(p.id, p.first_name, p.last_name)
q = simplejson.dumps({"person":person})
return HttpResponse(q, mimetype="application/json")
The above sends back a simple DOM element to the template and inserts it into a table at the bottom. Sliding in right to left.
If you send back the entire template, the entire screen will flash and won't get any slick animations. That is my understanding anyway.
I have done this for a couple of jQuery Dialogs. The dialog contents are requested by a AJAX request, the contents are rendered on server side and then returned and displayed. So far I have experienced no problems with that.
From personal experience i can say that there is no pitfalls. I just not very good design pattern (not good practice). I used to do that on pretty high loaded project.
I have had the same problem in the year 2023 (question was asked in 2012..). Django still doesn't support rendering a template without invoking the whole chain of template inheritance.
So here's a basic way of rendering partial template:
from django.template import Context, loader
def render_template_to_string(template_name, context=None):
template = loader.get_template(template_name).template
context_instance = Context(context or {})
with context_instance.bind_template(template):
return template.nodelist.render(context_instance)
And your (partial) template can be as simple as:
<ul>my partial list
{% for opt in options %}
<li>{{ opt }}</li>
{% endfor %}
</ul>
You then invoke it by e.g.
from django.http import HttpResponse
resp = render_template_to_string(
"path/to/partial/html", {"options": range(10)}
)
return HttpResponse(resp)
FYI you might want to add support for some node exclusions, error handling, or better flexibility of what gets passed to render_template_to_string.
Related
I can't understand different between Template tags and Context Processors in django template.
I already read this question. However I can't understand everything.
Template tags is used in easy processing, tailoring the data, etc., while Context Processors is used in getting entirely different data. Is my understanding correct?
I think Context Processors is easier to use because not need to {% load ~~ %}. Is the reason why Context Processors is not used? it's because it need to Heavy processing?
I'm sorry, my English is hard to understand :(
Waiting for your answer!!
For context processor the most important thing when you need to make something available globally to all templates.For example you can ask that like user is_ authenticated?, is_admin? and get_or_create group.It provide us global actions
They are two different things. context is data that you pass from a view to a template like user, form, some_object and ...
Django Template Tags are simple Python functions that accept one or more value, an optional argument, process those values and return a value to be displayed on the page.
Consider a template tag as a mini page with UI build and ready to be used in any page. It will appear the same way without any further modification. If you were to use context processor to provide data in every page, you'd have to write the html code to make the data appear the way you want. If that data needs to appear in many pages, you'd have to repeat the html code in each page.
Let me share my way of using the template tag and context processor.
context_processors.py
from billing.models import customerType
def get_menu(request):
customerTypes = customerType.objects.filter(active=True)
item = []
for customerType in customerTypes:
item = {
'name': customerType.name,
'slug': customerType.slug
}
cp_customerType_list.append(item)
return {'cp_customerType_list': cp_customerType_list}
settings.py
...
"context_processors": [
...
"billing.context_processors.get_menu",
...
],
...
customer_type_template_tag.py
from django import template
from django.http import request
from billing.context_processors import get_menu
register = template.Library()
#register.inclusion_tag('billing/tags/customer_types.html')
def get_customer_types_list():
return get_menu(request)
customer_types.html
<ul class="slide-menu">
{% for cp_customerType in cp_customerType_list %}
<li>
<a href="{% url 'billing_customer_list' customerType.slug=cp_customerType.slug %}">
{{cp_customerType.name}}
</a>
</li>
{% endfor %}
</ul>
base.html
<!doctype html>
...
<!-- at the top of the base.html page -->
{% load customer_type_template_tags %}
...
<!-- at the point of loading the customer types menu -->
{% get_customer_types_list %}
...
I'm trying to set value to Django session within the template and then posible used in the view.
I'm doing something like this
{% block body %}
<html>
{% request.session.fav_color="red" %}
<div> Is your favorite color {{ request.session.fav_color}} ?</div>
</html>
{% endblock %}
There are several reasons why this may not be a good idea:
Templates should deal with presentation only. If you are placing logic in the template it is supposed to be presentation logic. Placing business logic in the template is a violation of the SoC (separation of concerns).
Rendering the template often is one of the last things you do in a view so it is hard to get the cat back in the bag if you have already sent the data to the browser (and if you rendered the template but haven't sent data down the pipe you can just update the value in the view instead of trying to do it in the template).
If you are interacting with the user the traditional way to do it is using a form (even if it is a form with only the submit button) - or posting data to the server in the frontend using AJAX.
I am building an application with Django as the backend and React js for making the interface of the application.
I have a set of Posts which I want to display.
Currently, the approach which I am following is -
Get the template having the compiled js code linked to it.
Then again make get call to get the posts
My question is - In this current approach I am making 2 GET calls to the backend, one for rendering the template and then again for getting the Post.
What is the best way to achieve this? Is this the usual flow how applications are built using Django and React JS?
First off: I don't see anything wrong with doing this in two requests, because one loads the application itself and the second loads the content. To me this seperation makes sense and might turn out to be useful in the future if you want to reuse say the Endpoint, that yields the the posts(i.e. the content).
Answering your question: If, for whatever reason, you absolutely want to load everything with a single GET, a good way of doing so, would be to pass a list of posts to the context as a JSON-serialized object and then load these into the JS-context within the Django-template.
i.e. in the view.py:
from json import dumps
def view(request):
context = {
'posts':get_posts(),
}
render_to_response('django_template.html', context,
context_instance=RequestContext(request))
def get_posts():
qs = Posts.objects.all()
return dumps({'posts': qs })
in the django_template:
{% block content %}
<div id="root"></div>
{% endblock %}
{% block javascript %}
<script>
var INITIAL_POSTS = {{ posts|safe }};
</script>
<script type="text/javascript"
src="PATH_TO_STATIC_REACT_ASSET.JS"></script>
{% endblock %}
you should now have your posts in your JS context and can load them in your React component. Once again: I would agree with Daniel Rosemans comment
I want to keep my templates free of any logic - just html. I'm using a "for" loop in index.html to cycle through a list of posts. Here is the loop:
{% for recent in latest %}
<h1>{{ recent.title }}</h1>
<h2>{{ recent.category }}</h2>
{% endfor %}
What I want to do is in my Posts class, grab all the posts, checking that they match certain criterion, then place them in variables which could be sent to the template.
Here is the view (the logic of which I want to eventually move to models.py):
def index(request):
# Get latest five posts
latest_posts = Post.objects.order_by('-published_date')[:5]
# Get a single "top" category post.
top_post = Post.objects.get(category = 1)[:1]
# set up some contexts
top = {'front_post': top_post}
context = {'latest': latest_posts}
return render(request, 'home/index.html', context, top)
Any suggestions?
You're taking the idea of keeping templates free of logic too far. There's a reason template languages provide things like for loops and boolean logic: without them you will wind up breaking the separation of concerns that an MVC framework is trying to enforce. Because what you will wind up with is embedding presentation information in your view logic and that's not what you want. As a simplistic example, consider adding the option of viewing your posts as a text file without adding a second view. If you keep the markup in the templates, it's easy. If you don't, it's not possible.
I'm working on a project in Django.
Earlier today, I discovered the new (Django >= 1.4) assignment_tag. I immediately decided that it was just what I needed EVERYWHERE and threw some logic into one that executed a very simple query against the database and returned the resulting queryset. The function I wrapped takes an argument that allows the invoking context to specify how many results to grab, directly in the template when I am using the template tag.
It is quite convenient - I don't have to update my view when I decide this list should have 5 items, not 3 - but it seems like one of those gray areas where we aren't supposed to tread (i.e. pushing application logic into templates) when writing good, maintainable Django code.
Now, a couple of hours separated from writing the code, I'm wondering if I should scrap the assignment_tag entirely.
Code:
models.py:
class SomeObject(models.Model):
is_active = models.BooleanField(default=False)
(...)
templatetags/myapp_tags.py:
from django import template
from myapp.models import SomeObject
register = template.Library()
#register.assignment_tag
def get_someobjects_list(max_results=0):
queryset = SomeObject.objects.filter(is_active=True)
if max_results == 0:
return queryset
elif max_results > 0:
return queryset[:min(max_results, queryset.count())]
else:
return None
templates/myapp/chunks/someobject_list.html:
{% load myapp_tags %}
{% get_someobjects_list as someobjects_list %}
# or {% get_some_objects_list 5 as someobjects_list %} ... flexible!
{% if someobjects_list %}
<ul>
{% for someobject in someobjects_list %}
<li>
<a href="{{ someobject.get_absolute_url }}">
{{ someobject.name }}
</a>
</li>
{% endfor %}
</ul>
{% else %}
<span>No someobjects exist</span>
{% endif %}
I was really excited to discover these existed - it's convenient for me in this particular case. Now that my excitement over finding a new feature has passed, it seems pretty clear that I'm misusing it. The example given in the Django docs seems like a better application of this - grabbing the string representation of current datetime, something that doesn't require a DB query. My worry is that I'm setting myself up for heartache if I start using this pattern regularly. Following the slippery slope all the way down: I'll end up not even bothering to pass a context to my templates and ALL my DB queries will be hidden away in template tags where nobody would think to look for them.
It seems the code would be cleaner if I just threw out this whole "great idea" I had when I discovered assignment_tags and created a custom model manager instead.
Are there other clean ways of accomplishing this that I am missing? Are manager methods the consensus best way among Django developers?
assignment template tags are especially helpful if you need to get some information into the template context for a few pages of a website, but don't want to (or can't) put the info into every view on the website, and don't want to or can't rely on a context processor.
they basically guarantee that your information will be available in the template.