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.
signature.asc
Description: OpenPGP digital signature