Hi Emil,

On 06/02/2015 11:53 AM, Emil Stenström wrote:
> On Tuesday, 2 June 2015 19:06:35 UTC+2, Carl Meyer wrote:
>     Using Jinja2 on the server and nunjucks on the client with shared
>     templates works very well, is quite easy, and doesn't require
>     Node.js on
>     the server. I've been using this combination for a year and a half on
>     several different projects and am quite happy with it.
>  
> I'm very happy to hear that this works in production. I picked nunjucks
> as an example just based on reading about it, but now I know that this
> is something that actually works. Thanks for that!
> 
>     The primary discipline involved is ensuring that you only pass
>     JSON-serializable objects to your templates (this is required for any
>     template-sharing technique). In practice, this just means you need a
>     full set of serializers and to use them consistently. The same
>     serializers should be used in your server-side views and in your
>     API, so
>     the objects passed to your templates on the server and client side are
>     the same. (I think using serializers and avoiding passing model
>     instances/querysets directly into template contexts is a good practice
>     anyway.)
>  
> I would love to see some code here if you have it available? How do you
> pass the JSON and the templates from the view to the client side?

I don't have code I can share at the moment, but I'm hoping to blog
about this technique, and I'll let you know if/when I do.

It's not very complicated, though. Data gets from server to client in
one of two ways: either it is rendered to a template on the server side
from a normal Django view and then returned as an HTML HTTP response, or
it is queried by the client using XMLHttpRequest from a JSON API and
then rendered in (possibly the same) template on the client side. The
key is that you use the same serializers in both cases. So in one
project, we're using Django Rest Framework and DRF serializers. A simple
view might look like this:

    def person_detail(request, person_id):
        person = get_object_or_404(Person, pk=person_id)
        context = {
            'person': PersonSerializer(person).data,
        }
        return render(request, 'person_detail.html.j2', context)

And then there's also a set of DRF API endpoints for Person, using the
same PersonSerializer, so JS can query that API via XHR, and render the
very same 'person_detail.html.j2' template (or more likely, a partial
included in that template) on the client side.

Or sometimes JSON (in the same format, from the same serializers) gets
pushed to the client via Websockets (or SSE I suppose, though I haven't
used SSE myself) for real-time updates, where it again can be used to
render the same templates.

The templates get to the client via nunjucks precompilation. Nunjucks
can compile Jinja2 templates to a file of plain JS code, and then that
file is referenced like any other static JS asset. (Precompilation is a
build step, it doesn't happen at runtime.) What you end up with is a JS
object mapping template paths to functions that you call with a context
and get back HTML (and it's quite fast, since there's no template
parsing at runtime).

It's also possible to do things like smuggle JSON data in a <script
type="application/json"> tag along with an HTML skeleton and then render
that JSON on the client. Whether that performs better or worse than
simply rendering the template on on the server is a highly complex and
nuanced question, depending on factors like the size of the JSON data vs
the size of the rendered data, whether you care more about time to first
byte or time to last paint, what level of no-JS support you want, etc.
(See e.g.
http://www.onebigfluke.com/2015/01/experimentally-verified-why-client-side.html
for some exploration of this.)

Carl

>     The main problem is that if you want to extend the template language
>     with custom tags/filters, you have to write these extensions twice. We
>     tend to accommodate this by just writing many fewer template language
>     extensions, doing more display-preparation work in serializers instead,
>     and relying on Jinja's built-in expressive power (e.g. macros) instead
>     of template language extensions.
> 
> 
> Yeah, I figured as much. I think that Django is in a better position
> here than other frameworks since actual python code in templates are
> discouraged.

-- 
You received this message because you are subscribed to the Google Groups 
"Django developers  (Contributions to Django itself)" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to django-developers+unsubscr...@googlegroups.com.
To post to this group, send email to django-developers@googlegroups.com.
Visit this group at http://groups.google.com/group/django-developers.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/django-developers/556DF67C.7040300%40oddbird.net.
For more options, visit https://groups.google.com/d/optout.

Attachment: signature.asc
Description: OpenPGP digital signature

Reply via email to