sexta-feira, 12 de junho de 2015

AppRegistryNotReady: The translation infrastructure cannot be initialized before the apps registry is ready


Dê uma olhada em seu arquivo wsgi que carrega os módulos e apps. O erro acima é muito comum a partir do Django 1.7

Troque:
module = django.core.handlers.wsgi:WSGIHandler()



Por:
module = get_wsgi_application()



Exemplo:

import sys, os

sys.path.append(os.getcwd())

# CONFIGURACAO PARA ENV
sys.path.insert(0,'<CAMINHO PARA SEU ENV>/ENV/bin')
sys.path.insert(0,'/<CAMINHO PARA SEU ENV>/ENV/lib/python2.7/site-packages')
# -------------------------

sys.path.insert(1, "/<CAMINHO PARA SEU PROJETO>/app")
os.environ['DJANGO_SETTINGS_MODULE'] = 'app.settings'
import django.core.handlers.wsgi

#application = django.core.handlers.wsgi.WSGIHandler()

from django.core.wsgi import get_wsgi_application
application = get_wsgi_application()

quinta-feira, 22 de janeiro de 2015

Validações customizadas no forms.ModelForm com método clean para um atributo


As vezes alguns campos requerem validações além do tipo de dados neles inserido. Abaixo tem um exemplo que fiz para um caso desse.

A necessidade era validar um charfield de acordo com uma série de valores e por ser campo aberto não poderia fazer um choices.


models.py
class SuaClasse(models.Model):
 ...
 seu_atributo = models.CharField(max_length=20)
 ...

admin.py
from django.core.exceptions import ValidationError
import re

class SuaClasseAdminForm(forms.ModelForm):
 class Meta:
  model = SuaClasse

 def clean_seu_atributo(self):
  cleaned_data = super(SuaClasseAdminForm, self).clean()
  seu_atributo = cleaned_data.get("seu_atributo")
  if not seu_atributo in ['TL','TR','BR','BL','C','R']:
   m = re.search('[0-9]*(%)*x[0-9]*(%)*', seu_atributo)
   if not m:
    raise ValidationError("Preencha o atributo com uma das opções disponíveis.")

class SuaClasseAdmin(admin.ModelAdmin):
 form = SuaClasseAdminForm

 ...

No exemplo acima, preciso que o valor de seu_atributo seja um dos valores contidos na lista ['TL','TR','BR','BL','C','R'] ou respeite a expressão regular que testa para os seguintes exemplos: 300x200, 50%x300, 40x90% ou 150x400.

O que podemos notar é que o método clean_seu_atributo fará a validação no campo especificado e trará o erro logo acima do campo em caso de falha. Também é possivel fazer somente o método clean, contudo o erro será mostrado no início do form, sem vínculo a campo algum.


hasta!

quarta-feira, 21 de janeiro de 2015

Como criar um PNG com marca d'água e texto dinâmico

A necessidade: Criar uma ferramenta para upload de uma imagem e gerar uma saída com uma marca d'água e um texto dinâmico. Saída era esperada em PNG para melhor renderização no Facebook.

Pra isso, você vai precisar de:
  • PIL==1.1.7
  • django-easy-thumbnails-watermark==0.6.7

Crie uma classe no models.py para tal:
class Visita(models.Model):
 """(Visita description)"""
 data = models.DateField(auto_now_add=True)
 linha1 = models.CharField(max_length=255)
 linha2 = models.CharField(max_length=255, null=True, blank=True,)
 imagem = models.ImageField(upload_to="uploads/visitas/imagem/%Y",help_text="800x671")

 class Meta:
  verbose_name, verbose_name_plural = u"Visita à Fábrica" , u"Visitas à Fábrica"
  ordering = ('-data',)

 def __unicode__(self):
  return u"%s" % self.data


 def gerar(self):
  return 'Gerar' % self.id
 gerar.allow_tags = True
 gerar.is_safe = True

Aqui criei um modelo que tem uma data, por questão de organização, duas linhas para texto que serão inseridas na imagem e a imagem em si.

No urls.py, crie uma entrada para chamada da view:
url(r'^visitas/(?P\d+)/$', 'imagens_facebook.views.visitas', name="visitas"),

E da view abaixo:
def visitas(request, vid):
 img_obj = get_object_or_404(Visita, id=vid)
 img = '{0}/{1}'.format(settings.MEDIA_ROOT, img_obj.imagem)
 IMAGE = Image.open('{0}/{1}'.format(settings.MEDIA_ROOT, img_obj.imagem))
 WM = {
  'image':'{0}/site/img/visita.png'.format(settings.STATIC_PATH,),
  'position': 'BL',
  'opacity': 1,
  'scale': 1,
  'tile': False,
  'greyscale': False,
  'rotation': 0,
 }
 WK_DONE = watermark_processor(IMAGE, WM )
 path = '{0}/watermarks/visitas/{1}'.format(settings.MEDIA_ROOT, 'imagem.png')
 WK_DONE.save(path, "PNG")
 img = Image.open('{0}/watermarks/visitas/{1}'.format(settings.MEDIA_ROOT, 'imagem.png'))
 draw = ImageDraw.Draw(img)
 font = ImageFont.truetype("{0}/fonts/trebuc.ttf".format(settings.STATIC_PATH),20)
 draw.text((60, 465), img_obj.linha1.upper() ,(55,185,115),font=font)
 if img_obj.linha2:
  draw.text((60, 490), img_obj.linha2.upper() ,(55,185,115),font=font)
 img.save('{0}/watermarks/visitas/{1}'.format(settings.MEDIA_ROOT, 'imagem.png'))
 return force_download(request, path)

Linha a linha temos:

  1. Definição da View "visitas" que recebe o request e o id da visita, identificado por "vid"
  2. Obtenção do objeto visita com o id informado
  3. Definição do caminho de onde está a imagem que foi feita upload
  4. Abertura da imagem como objeto da Classe Image
  5. Definição da WaterMark com o parâmetros necessários:
    1. caminho da marca d'agua
    2. Posição que será inserida, BL para bottom left
    3. Opacidade =1 para não ter transparencia, do contrario coloque valores entre 0 e 1.
    4. Escala 1 para não alterar o tamanho
    5. Tile é falso para não esticar imagem utilizada como marca d'agua em toda a imagem definida no upload.
    6. Escala de cinza falso para sair colorido
    7. Sem rotação para sair em orientação normal.
  6. Criação da imagem com marca d'agua utilizando o watermark_processor
  7. Definição de onde será gerado o arquivo
  8. Ação de salvar para gerar o arquivo em png
  9. A partir desta linha é onde será escrito o texto dinamico. Aqui abrimos a imagem gerada no passo anterior.
  10. Criação de um objeto draw da classe ImageDraw.
  11. Definição da fonte a ser utilizada. Aqui será necessário copiar o arquivo da fonte para seu projeto.
  12. A escrita do texto proprimente dita com os respectivos parâmetros: posição(left, top), texto a ser inserido, cor em RGB e caminho da font definida no passo anterior
  13. Apenas um if para testar se há uma segunda linha no texto.
  14. Se houver repete a mesma ação do passo 12, passando o texto diferente.
  15. Ação de salvar a imagem para gerar o arquivo físico.
  16. View para forçar o download do arquivo gerado. Esta view pode ser vista aqui: http://djangoweb.blogspot.com.br/2011/10/forcando-download-de-arquivos-no-django.html

hasta!