In Django, where is the best place to put short snippets of HTML-formatted data?

This question is related to (but perhaps not quite the same as):

Does Django have HTML helpers?

My problem is this: In Django, I am constantly reproducing the basic formatting for low-level database objects. Here's an example:

I have two classes, Person and Address. There are multiple Addresses for each Person, setup likeso (in their respective models.py)

class Person(models.Model):
  ...

class Address(models.Model):
  contact = models.ForeignKey(Person)

Now, whenever I look at a Person, I want to see all their Addresses. So suppose Persons/views.py has something likeso:

def detail(request, person_id):
   person = get_object_or_404( Person, pk=person_id )
   return render_to_response('persons/details.html',
      { 'title' : unicode(person), 'addresses': person.address_set.all() } )

And, I have a template, persons/details.html, with code, for example, like-so:

{% extends "base.html" %}

{% for address in addresses %}
<b>{{ address.name }}</b>
  {{ address.type }} <br>
  {{ address.street_1 }}<br>
  {{ address.street_2 }}<br>
  {{ address.city }} {{ address.stateprov }} {{ address.postalcode }}<br>
  {{ address.country }}
  <hr>
{{ endfor }}

I am repeating this code quite a bit, often with minor variations, such when it's in a table, and then < br > must be substituted by < /td >< td >. Other times, I don't want a street_2 to display (or the < br > after it). All to say, there is fundamental logic that I want to express, that I am even more loath to tote around with block-and-copy!

What I want is a persons/details.html with, for example, the following:

{% extends "base.html" %}
{% for address in addresses %} 
  {% address.as_html4 %}
{% endfor %}

And if I want inline table, something likeso (I guess!):

{% extends "base.html" %}
<table><tr>
{% for address in addresses %}
  <tr><td> {% address.as_html4 </td><td> %} </td></tr>
{% endfor %}
</table>

The question is, then: Where is the best place to put the formatting? The logic?

Django seem to have the following (plausible) options:

  1. Put the formatting in models.py

  2. Put the logic/formatting in views.py

  3. Put the logic/formatting in some other sub-class of Person or Address (i.e. addresses/html4.py)

  4. Create custom tags

Help / insight much appreciated!


Asked by: Thomas268 | Posted: 01-10-2021






Answer 1

Sounds like an inclusion tag is what you're looking for. You could have a template and tag for each major variation and use the tag's arguments to customise the context for each template as required.

Basic tag definition:

@register.inclusion_tag('person/address.html')
def display_address(address):
    return {'address': address}

Use in templates (assuming the templatetag module containing it has already been {% load %}-ed):

{% display_address address %}

Answered by: Michael908 | Posted: 02-11-2021



Answer 2

I would use a template tag outputting data using a template html-file a k a inclusion-tag

Answered by: Maya452 | Posted: 02-11-2021



Answer 3

I think template filter will be useful too. You can pass filter on each object, for example:

{{ value|linebreaks }} # standard django filter

Will produce:

If value is Joel\nis a slug, the output will be <p>Joel<br>is a slug</p>.

See Django Built-in template tags and filters complete reference.

Answered by: William730 | Posted: 02-11-2021



Similar questions

Python - Send HTML-formatted email via Outlook 2007/2010 and win32com

Is there a way to send HTML-formatted email using Python's win32com.client (which utilizes Outlook 2007/2010). The format I'm using now looks like this: import win32com.client olMailItem = 0x0 obj = win32com.client.Dispatch("Outlook.Application") newMail = obj.CreateItem(olMailItem) newMail.Subject = "the subject" newMail.Body = "body text" newMail.To = "recipient@example.com" attachment1 = "c:\\mypic.jpg"...






Still can't find your answer? Check out these communities...



PySlackers | Full Stack Python | NHS Python | Pythonist Cafe | Hacker Earth | Discord Python



top