Templates Django: Filtro truncatewords melhorado

O filtro truncatewords do Django pode ter resultados muito diferentes devido à variação da largura das palavras.

Entre “as”, “os” e “es” pode-se ter “paralelepipedos”, “instrumentações” e “inconstitucionais”.

Sei que estou exagerando, de 6 passamos para quase 50 caracteres, mas é só para provar o meu ponto.

Pensando nisso criei um filtro para se usar nos templates do Django. Aí vai:

from django import template

register = template.Library()

@register.filter
def truncatesmart(value, limit=80):
    """
    Truncates a string after a given number of chars keeping whole words.

    Usage:
        {{ string|truncatesmart }}
        {{ string|truncatesmart:50 }}
    """

    try:
        limit = int(limit)
    # invalid literal for int()
    except ValueError:
        # Fail silently.
        return value

    # Make sure it's unicode
    value = unicode(value)

    # Return the string itself if length is smaller or equal to the limit
    if len(value) <= limit:
        return value

    # Cut the string
    value = value[:limit]

    # Break into words and remove the last
    words = value.split(' ')[:-1]

    # Join the words and return
    return ' '.join(words) + '...'

Postei também no Django Snippets: Truncate string after a given number of chars keeping whole words.

Para usar este filtro no seu projeto basta colocar o código acima em um arquivo “.py” dentro do diretório “templatetags” de alguma aplicação e habilitar a aplicação no settings.py do seu projeto. Exemplo da estrutura de arquivos:

  • projeto
    • app
      • templatetags
        • __init__.py
        • app_tags.py
      • __init__.py
      • views.py
      • models.py
    • __init__.py
    • settings.py

No seu template, você precisa chamar a biblioteca de tags recém-criada (app_tags.py) e aí é só usar o filtro:

{% load app_tags %}
{{ string|truncatesmart:50 }}

Para mais informações, veja a documentação sobre como criar suas templatetags e filtros.

[Update em 07/01/2009] Adicionadas instruções sobre como utilizar o filtro no seu projeto, a pedidos de Lucas Max (valeu Lucas).

Anúncios

Herança no Django (Model Inheritance)

Recentemente estava trabalhando com herança de modelos no Django (model inheritance para os estrangeiros) e precisei saber, à partir da classe mãe, qual era a classe filha.

Até então não tinha me preocupado como funcionam as “entranhas” do Django pra dar suporte à herança de modelos, é interessante.

Os dados da classe mãe são salvos em uma tabela, e os das filhas em outra, uma nova tabela para cada filha. Quando é carregada uma instância da classe filha, ela traz consigo os dados herdados da mãe (através de um JOIN no banco). Já a mãe pode ser chamada de desnaturada, não é muito boa para achar suas filhas.

Então o que eu fiz foi adicionar uma relação genérica à classe mãe e alterar o método save para relacionar à classe filha apenas gravando o content-type, assim eu consegui fazer a família se comunicar melhor.

Depois que postei no Django Snippets vi que mais gente tinha feito algo parecido, mas eu juro que só vi depois! 🙂

De qualquer forma, aí vai:

from django.contrib.contenttypes.models import ContentType
from django.contrib.contenttypes import generic

class Place(models.Model):
    name = models.CharField('name')
    content_type = models.ForeignKey(ContentType)
    # Child model
    child = generic.GenericForeignKey(fk_field='id')

    def save(self, **kwargs):
        if not self.pk:
            self.content_type = ContentType.objects.get_for_model(self)
        super(Place, self).save(**kwargs)

class Restaurant(Place):
    pass

Ou veja no Django Snippets, lá fica mais bonito: Child aware model inheritance.

Tem algumas variações aqui.