terça-feira, 25 de outubro de 2011

Caught NoReverseMatch while rendering..

Algumas aplicações que utilizam do fantástico recurso de urls nomeadas, precisam ter os includes declarados no urls.py raiz do projeto.

Nem sempre a gente lembra, e acaba pegando umas telas bonitas dessa:



Basta uma conferida no arquivo urls.py da raiz e corrigir o problema incluindo as urls que faltam.


hasta!

segunda-feira, 17 de outubro de 2011

Plugins Úteis - Sorl e o (muito util) ThumbnailField

Para quem utiliza a fantástica biblioteca Sorl Thumbnail (http://pypi.python.org/pypi/sorl-thumbnail), tem uma funcionalidade muito útil além da inclusion tag {% thumbnail %}

Com a inclusion tag, é possível redimensionar e/ou cortar, uma imagem de acordo com a necessidade. Para isso, basta utilizar assim no seu template:

{% load thumbnail %}

A linha acima deve ser colocar no começo do arquivo para carregar as tags da sorl para seu template. E para a imagem fazemos:

<img src='{% thumbnail seu_objeto.campo_foto 150x150 crop,upscale %}' />

Aqui temos um exemplo em que será gerada uma imagem de 150px de largura por 150px de altura. As opções crop,upscale são opcionais e servem para corte e redimensionamento, respecticamente.

Há uma certa desvantagem em utilizar desta forma. A thumb somente será gerada quando alguma requisição for feita para a página, e após isso o arquivo físico da thumb é gerado em tempo de execução. Posteriormente, se a thumb não for trocada, o sistema utiliza a thumb gerada na primeira requisição ao invés de gerar uma nova.

Uma outra opção, e fazer a geração de todas as thumbs utilizadas para uma mesma foto, no momento que a foto é inserida ou alterada. Para isso temos o ThumbnailField.

No seu model, já com a sorl instalada no seu projeto e/ou no virtualenv, faça:

No ínicio do arquivo models.py que for utilizar thumbs, import o ThumbnailField:

from sorl.thumbnail.fields import ThumbnailField

E na sua classe, crie o campo com o campo importado da seguinte forma:

class SuaClasse(models.Model):
    foto = ThumbnailField(
upload_to="uploads/banners/home/%Y",
help_text=u"Tamanho mínimo e proporcional a 1024x768",
options = ('upscale',),
size = (1920,1000),
generate_on_save = True,
extra_thumbnails={
'1024x768':{ 'size':(1024,768), 'options':('upscale',) },
'1280x1024':{ 'size':(1280,1024), 'options':('upscale',) },
'1280x800':{ 'size':(1280,800), 'options':('upscale',) },
'1440x900':{ 'size':(1440,900), 'options':('upscale',) },
'1366x768':{ 'size':(1366,768), 'options':('upscale',) },
},

Deste modo, teremos 6 arquivos para cada imagem que for inserida.

  • A original foto,  que terá no máximo 1920x1000 px de tamanho, sendo que fará uso do upscale
  • E 5 extra_thumbnails, onde cada uma terá um tamanho próprio, também utilizando o upscale.

No template para utilizar o campo foto,  nada muda, continua sendo :

{{ seu_obj.foto }}

Já para acessar alguma das thumbs, utilize:

{{ seu_obj.foto.extra_thumbnails.NOME_DO_THUMBNAIL }} ,  por exemplo:

{{ seu_obj.foto.extra_thumbnails.1280x1024 }} 


Em alguns casos temos que acessá-los em uma view, seja para montar um json para o ajax, ou até mesmo um xml pro inútil e arcaico Flash. Para isso utilize:

seu_obj.foto.extra_thumbnails_tag['1280x800']


Outra opção é criar um model, muito útil para quando deseja-se mostrar a thumb no change list do admin. Para isso, utilize:


def thumb_admin(self):
from sorl.thumbnail import get_thumbnail
im = get_thumbnail(self.imagem, '120x120', crop='center', quality=99)
if im:
return  '<a href="%s/"><img src="%s" alt="Imagem" /></a>' % (self.id, str(im.url))
return  'Sem foto'
thumb_admin.is_safe = True
thumb_admin.allow_tags = True
thumb_admin.short_description = 'Thumb'


hasta!








terça-feira, 11 de outubro de 2011

Forçando download de arquivos no Django

Muitas vezes, nossas classes possuem módulos que tem imagens em alta definição, ou até mesmo arquivos referente ao contexto da classe, tais como manuais em pdf, ou em outro formato qualquer.

Para algumas situações é melhor que o visitante faça download do arquivo, mesmo que o browser possua os plugins necessários para exibí-lo. Para forçar o download basta utilizar a view abaixo:


def download_view(request):
 from django.http import HttpResponse, Http404
 from os import path
 import mimetypes

 arquivo = "%s/%s" % (settings.MEDIA_ROOT, request.GET.get('filename'), ) 

 if not (path.exists(arquivo)):
  raise Http404()

 mimetype, encoding = mimetypes.guess_type(arquivo)

 if mimetype is None:
  mimetype = 'application/force-download'

 file = arquivo.split("/")[-1]

 response = HttpResponse(open(arquivo, 'r').read())
 response['Content-Type'] = mimetype
 response['Pragma'] = 'public'
 response['Expires'] = '0'
 response['Cache-Control'] = 'must-revalidate, post-check=0, pre-check=0'
 response['Content-Disposition'] = 'attachment; filename=%s' % file
 response['Content-Transfer-Encoding'] = 'binary'
 response['Content-Length'] = str(path.getsize(arquivo))
 return response


O parâmetro filename vem por get, permitindo que a mesma view seja utilizada para vários downloads de diferentes classes. O que pode ser ajustado é o caminho da definição da variável filename de acordo com a necessidade.

hasta!