Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Django: Implementing a nested, reusable component design

I'm working on a big social networking app in Django where I expect to use certain front-end components many times, and often with functionality designed in such a way that custom components contain other custom components, which might contain yet smaller subcomponents (ad infinitum). All of these components are typically dynamic generated. I'm trying to figure out the best way to architect this in the Django framework, such that my components are easy to maintain and have clear programming interfaces. Relying heavily on global context would seem to be the opposite of this, however, I can see advantages in avoiding redundant queries by doing them all at once in the view.

Custom inclusion template tags seem like a good fit for implementing components, but I'm wondering, do highly nested template tags can create performance issues, or does the parsing architecture prevent this? What is the best way of making it self-documenting at the view level what context is needed to render the main page template, custom tags and all? I'm imagining it to be a minor nightmare to try to properly maintain the code to set up the template context. Lastly, what is the best way to maintain the CSS for these components?

Feel free to suggest other recommended approaches for creating a nested-component design.

like image 356
acjay Avatar asked Nov 12 '12 21:11

acjay


People also ask

How do I reuse a Django template?

To reuse a Django template you use the Django built-in {% extends %} tag. The {% extends %} tag uses the syntax {% extends <name> %} to reuse the layout of another template. This means that in order to reuse the layout in listing 3-10 defined in a file base. html , you use the syntax {% extends "base.

What is DTL in Django?

Django Template Language (DTL) is the primary way to generate output from a Django application. You can include DTL tags inside any HTML webpage. The basic DTL tag you can include in an HTML webpage is: 1. {% Tag %}

What {{ NAME }} means in a Django template?

What does {{ name }} this mean in Django Templates? {{ name }} will be the output. It will be displayed as name in HTML. The name will be replaced with values of Python variable.


1 Answers

The solution I've decided on so far is to go ahead with using an inclusion tag library as my set of reusable components. I'm sticking as much as possible to setting up all queries in my view code, and passing them in pre-setup in my context--no functions that generate new queries in templates or tag library code. The inclusion templates contain all of the markup for the item, and the styles go into the main site stylesheet, keeping my classes as generic and reusable as possible, following the guidelines of SMACSS. I refactor components into inclusion tags only as DRY requires.

I initially made my inclusion tag functions explicitly take the parameters used by the tag template, such that:

Page template

<div>{% my_tag param1 param2 %}</div>

Tag library

@register.inclusion_tag('myapp/tagtemplates/my_tag.html')
def my_tag(param1, param2):
    return {'param1': param1, 'param2': param2}

my_tag.html

<div>Blah: {{ param1 }}</div>
<div>Blip: {{ param2 }}</div>

...and obviously the view sets up the context.

But I decided instead to use the takes_context parameter to avoid explicitly defining the parameters in the tag library. Too much repetition for not enough payoff in documentation. So far, my components are simple enough that the dependencies are pretty clear from inspection of the tag template. I worry that this might not be acceptable with complicated nested components, but I can always make my tag library functions verbose, where they need to be.

I'm not entirely pleased with this setup from a maintenance standpoint. I don't like that I will have to manually track what context data is no longer needed. I don't like the fact that my CSS classes will have to be carefully named to avoid clashes.

I am still open to new solutions, because I'm not sure that what I've decided really is a best practice.

like image 129
acjay Avatar answered Sep 20 '22 11:09

acjay