How to make reuseable blocks of HTML based upon a model object - django

Say I have a simple model with Title, Price, Description and Image fields. I would like 3 html outputs/blocks that I can reuse for each object of this model. For added 'complexity', 2 of the outputs will be combined to make the 3rd. So, here is what these 3 output might look like in a template.
output_image
<span class="output_image"><img src="{{ object.image.url }}" alt="{{ object.title}}></span>
output_info
<ul class="output_info">
<li>{{ object.title }}</li>
<li>Price: {{ object.price }}</li>
<li>{{ object.description }}</li>
</ul>
output_all (wraps up the previous 2)
<div class="output_all">
<span class="output_image">...</span>
<ul class="output_info">...</ul>
</div>
I might want to use output_image on a search page, and output_all on listing and advanced search, for example. Hence I only want to write this output once, and reuse it. What is the best way to achieve this?
Initially I thought to add methods/properties to the model class, which would return the formatted html. This worked, and in my template I could just call {{ object.output_all }}, for example. Is it bad practice to output html like this?
I have briefly looked at other ways too. Inclusion tags seems to work, but I have only tested with a 'complete' version of the output_all case (ie have not 'nested' the other 2 output tags within output_all yet). Is this the correct method, and is it possible to 'nest' the tags?

I would use inclusion tags for this. Keep presentation logic where it belongs, in templates.

Related

Adding an if statement to django-cms template tag

I'm probably missing something very obvious but can't see anything in the documentation. I have a carousel with a and each will hold an image. However I've added 6 but I want to add an if statement so if an Image has not been added you don't see a blank space, where there is no content inside the .
Here is what i've tried so far:
{% if "Carousel 1" %}
<li>
{% placeholder "Carousel 1" %}
</li>
{% endif %}
Attempt 2:
{% placeholder "Carousel 1" as cara1 %}
{% if cara1 %}
<li>
{{ cara1 }}
</li>
{% endif %}
Not sure if there is something differnt i need to be doing for the django-cms template tags?
Any help would be much appreciated. Docs here - http://docs.django-cms.org/en/latest/advanced/templatetags.html#placeholder
Not to be rude, but your approach is way, way off :)
Placeholders hold Content Plugins. Content Plugins are responsible for how they render their contents.
My advice would be to create or find a carousel content type plugin. This plugin will hold multiple images or "CarouselImage" model instances that you can iterate over, and also specify a template with which to render itself.
In this template resides the conditional statement you're wanting to check for. Placeholders are just that - places held for content plugins.

Django not displaying images from blog Post

I have created a DJANGO blog-engine which takes my post and the template parses it for html tags. links etc.. are working but it does not load image file and instead shows the 'alternative' . I have tried the tag in separate html files and it is otherwise. Just not displaying image from inside a django blog post.
Relevant portions of the template file :
{% include 'blog/header.html' %}
</aside>
<section id ="content">
<article>
{%for post in posts %}
<h2>{{ post.title }}</h2>
<h3>{{ post.created}}</h3>
<p>
{{ post.body|safe }}<br>
</p>
<h3>By {{ post.author }}</h3>
I am copy-pasting the post in question
<---- text here ------------------>
GDCM::Directory
<img src="/home/usman/www/deejay/blog/static/images/dicomdir.png" />
This is it
Interestingly, the 'a' tag works fine but the 'img' tag is not working. I have tried many variations but i want some inline code to display simple html tag, alternatively of course i will resort to it programmatically by passing some variable to the template from inside the post to let it know where to position the image.
Your problem is here: {{ post_get_absolute_url }}. You should use {{ post.get_absolute_url }}.
The better way is to call the URL of the image directly; that way you maintain your URLs in urls.py and not in your model code. It makes your app more portable.
Take your image field name value from your model, and then {{ post.image.url }}. For example, if your model is:
class Post(models.Model):
img = models.ImageField(upload_to='images')
Then you would use {{ post.img.url }}
Problem solved when I replaced the full address with
<img src="/static/images/dicomdir.png"/>
On development server as well as on production. What helped was that I looked at the Dev-server responses on my terminal and was able to figure out the url.

Rendering Foreign Keys in templates grouped by origin

I have an Area model, and I have Service model. Area is a Foreignkey of Service.
I want a template which shows each Service grouped under its respective Area, i.e.
Area 1
- service a
- service b
Area 2
- etc.
I've passed in an object list of all services to service_list.html. I have a custom tag get_areas which returns the areas, on which I can create the Area divisions, and from which I can potentially pass an area name to a service filter. But since I can't filter (can I?) in {% for service in object_list %}, how can I filter the service list in each Area's section of the HTML?
Thanks so much in advance.
If you post your models I can give you the exact code, but in general something like this should work:
# Pass in 'areas' variable from view with all required areas
{% for area in areas %}
{{ area.name }}
{% for service in area.service_set.all %} #Gets all the services associated with an area
{{ service.name }}
{% endfor %}
{% endofor %}
Not sure you even need a custom tag, but maybe I just don't understand that part.
Take a look at the regroup template tag. It was built for exactly the same purpose
https://docs.djangoproject.com/en/1.3/ref/templates/builtins/#regroup
One thing that I have realized is that once you get the point of displaying complex interrelated data in your templates, that it makes sense to transform the data into an appropriate object (generally a list of dictionaries) before passing them onto the template.
That way, you can test your information easier, and have a much easier time displaying it. (You'll have much powerful tools at your disposition in Python based Views than in Django Templating Language).
#Maz - thank you for that. I'm learning at the moment and need to look at service_set.
#arustgi - that worked perfectly. For the benefit of fellow novices stumbling over this, I pass in 'queryset': Service.objects.all() and use:
{% regroup object_list by area as area_list %}
{% for area in area_list %}
<h2 class="separate">{{ area.grouper }}</h2>
{% for service in area.list %}
<div class="column">
<h3>{{ service.title }}</h3>
{{ service.body }}
</div>
{% endfor %}
{% endfor %}
Concise, descriptive code. Many thanks, both of you

Django template formatting leads to "ragged" html

To my convenience I use some formatting in my templates (line breaks, spacing, etc.) For example:
{% extends "base.html" %}
{% load tabs %}
{% block content %}
{% block navigation %}
<ul id="user_admin_tabs_list">
<li><a href="{% url user_admin.views.profile %}" class=
{% ifactivetab "user_admin_tabs" "profile" %}
"user_admin_tabs_active_tab"
{% else %}
"user_admin_tabs_inactive_tab"
{% endifactivetab %}>Профиль</a></li>
...
But this leads to "ragged" html output. Like this:
<ul id="user_admin_tabs_list">
<li><a href="/accounts/profile/profile/" class=
"user_admin_tabs_active_tab"
>Профиль</a></li>
<li><a href="/accounts/profile/shops/" class=
"user_admin_tabs_inactive_tab"
>Магазины</a></li>
<li><a href="/accounts/profile/billing/" class=
"user_admin_tabs_inactive_tab"
>Биллинг</a></li>
<li><a href="/accounts/profile/settings/" class=
"user_admin_tabs_inactive_tab"
>Настройки</a></li>
</ul>
Therefore readability of templates causes bad readability of output html.
What is the decision of this problem?
To be honest, I wouldn't worry about the output of the template engine. You're going to be editing the templates, not the output, so for maintainability, it only really matters if the template HTML is well-structured. Sure, if someone uses "View Source" on your webpage, they'll see a mess of HTML, but that doesn't really matter that much.
That said, you could try using Django's spaceless tag to get prettier HTML output.
Edit
For this specific case, you could put the ifactivetab tags inline:
<li>Профиль</li>
I've thought about this in the past.
Your best bet IMO is to post process the output with something like tidy. It's written in C so it's pretty fast and won't incur much of a performance hit. It's an option in development but not something you want in production on a high traffic site.
You'll want to configure it to only indent code.
Off hand, I think it might try to clean up invalid markup which'll leave you scratching your head when you enable/disable it. Something to be aware of because the structure of your document might change as a result.
It's kind of nice if you're "viewing source" but you're probably better off just using firebug to examine your output anyway - if that's the motivation.

How to organize checkboxes in several columns in Django forms

I am a newbie to Django and web-development in general so be patient for maybe a very dumb question :)
I have a form generated from a model and in this form I have about 20 checkboxes. Now they are aligned in one long column and it looks not very nice from a UI point of view. I'd like this column to be split in several ones but still have this form be automatically generated from the model. What would you suggest me to do?
In the generated HTML individual checkboxes look like this:
<li><label for="id_boxes_0"><input type="checkbox" name="boxes" value="1" id="id_boxes_0" /> some name</label></li>
You don't need to change anything in Python code, but you'll need to layout the form in the template instead of using {{ form.as_ul }}. You can iterate over the form to get the fields. For the simplest possible approach, something like the following could put twenty fields in two columns of ten:
{% for field in form %}
{% ifequal forloop.counter 11 %}</ul><ul>{% endifequal %}
<li>{{ field }}</li>
{% endfor %}
Personally I never use the as_* helper methods in real code, as far as I'm concerned they're only useful for rough prototyping.