sexta-feira, 31 de agosto de 2012

Removendo acentos e caracteres especiais de nomes de arquivos durante o upload

Pior coisa para um programador, são nomes de arquivos com acentos, espaços e caracteres especiais. Pior que isso só os usuários malditos que insistem em continuar com esse procedimento infeliz.

Para resolver o problema de uma vez por todas, sempre que tiver um ImageField ou um FileField em seu model, utilize da seguinte maneira:
def retira_acento_upload(objeto, arquivo):
 """
 Essa função irá normalizar como um slug, o nome do arquivo que está sendo gravado e, irá gravá-lo
 em /media/uploads/APPNAME_CLASSNAME/ANO/nome_do_arquivo_normalizado.extensao
 """
 import os, datetime
 from django.template.defaultfilters import slugify
 caminho = str( '%s/%s/%s' % ( objeto._meta.app_label, objeto.__class__.__name__, datetime.datetime.now().year ) ).lower()
 nome, ext = os.path.splitext( arquivo )
 url = slugify( nome[:15] )
 return os.path.join( 'uploads', caminho, url+ext )

class SuaClasse(models.Model):
    ...
    arquivo = models.FileField(upload_to=retira_acento_upload)
    ...

Customize o return da def acima da maneira que desejar. No exemplo acima, o arquivo será enviado para uploads/<nome_da_app>/<nome_da_classe>/<ano_atual>/<nome_do_arquivo_nomalizado>.<extensão>

hasta!






segunda-feira, 27 de agosto de 2012

Extraindo os links de um campo HTML com expressão regular

Desenvolvendo uma ferramenta para mala direta, é importante que os links sejam contabilizados para poder mensurar os resultados.

Mas como fazer isso, sendo que o html será um campo RichText (django-ckeditor) com quantos links o usuário desejar?

O ckeditor gera no banco de dados, um campo do tipo Text e grava o conteúdo inserido em HTML. Para extrairmos os links, basta utilizarmos a mágica da expressão regular.

A estrutura ficou assim:

  • MalaDireta: Uma classe que contém o conteúdo html a ser enviado
  • Links: Uma classe que amarzenará os links gerados pela classe anterior 
Na classe MalaDireta, sobrescreva o método save e deixe-o da seguinte forma:

def save(self):
    self.link_set.all().delete()

    for u in re.findall(r'href=[\'"]?([^\'" >]+)', self.html):
        L = Link(
            maladireta = self,
            link = u,
        )
        L.save()
        self.corpo = self.corpo.replace(u, "%s/verify_url/%s" % (settings.SITE_URL,L.id))
    super(MalaDireta, self).save()

Desta forma, sempre que for alterada, a mala direta irá excluir todos os links vinculádos a ela, e inserir os novos links presentes no corpo.

Depois é só fazer uma view mapeada para a url inserida no replace acima, para contabilizar a visita, e fazer o redirect para o link original.


  • A expressão regular acima, foi testada e consegue recuperar as urls com os seguintes padrões: http://www.sua_url.com http:// 
  • www.sua_url.com.br http:// 
  • www.sua_url.com#sua_ancora http:// 
  • www.sua_url.com?seu_parametro=seu_valor 
  • http:// www.sua_url.com?seu_parametro=seu_valor#sua_ancora 
  • https://www.sua_url.com?seu_parametro=seu_valor#sua_ancora 
  • https://www.sua_url.com?seu_parametro1=seu_valor1&seu_parametro2=seu_valor2#sua_ancora 
  • https://www.sua_url.com/sua_pasta/?seu_parametro1=seu_valor1&seu_parametro2=seu_valor2#sua_ancora 

hasta!

quinta-feira, 23 de agosto de 2012

Personalizando o template Inline de um model

Para colocar um template personalizado no seu inline, basta adicionar atributo template no seu Inline, como no exemplo abaixo:

class FotoInline(admin.TabularInline):
    template = 'admin/galeria/edit_inline/tabular.html'
    model = Foto
    extra = 5


hasta!

quarta-feira, 22 de agosto de 2012

decoder jpeg not available

Estava usando a sorl-thumbnail (instalada no virtualenv do vagrant) para geração das thumbs e obtive o erro decoder jpeg not available. Para resolver este problema, desisntalei a PIL do virtualenv com o comando:

pip uninstall PIL

Após isso procurei nos repositórios pelo pacote libjpeg com o comando:

sudo apt-cache search libjpeg

Para instalar basta escolher qual deseja e executar o comando abaixo:

sudo apt-get install libjpeg62-dev

E após instalado, reinstale a PIL:

pip install PIL


hasta!

quarta-feira, 15 de agosto de 2012

utf8_general_ci vs utf8_unicode_ci


Execução


utf8_general_ci é muito mais rápido em comparação e classificação, porque só os tipos de cada carácter como um único valor, isto é, para comparação e seleção, cada carácter é convertido em um único valor numérico e, em seguida, estes valores são comparados.

utf8_unicode_ci usa um algoritmo de comparação muito mais complexo, onde até 4 parâmetros devem ser levados em conta para cada carácter.

Precisão de classificação em vários idiomas


utf8_unicode_ci é baseado no padrão Unicode para a classificação. utf8_general_ci é bem próximo, mas não é compatível com Unicode, porque foi adaptado para se tornar mais rápido.

Unicode define conjuntos de regras para como os caracteres devem ser classificados. Estas regras devem ter em conta as convenções locais, nem todos os tipos de seus caracteres no que poderíamos chamar de 'ordem alfabética'. Quanto a idiomas latinos, não há muita diferença entre a triagem e a classificação Unicode utf8_general_ci simplificado no MySQL, mas ainda existem algumas diferenças.

Por exemplo, os tipos de agrupamento Unicode "ß" como "ss", e "Œ" como "OE", enquanto que os tipos utf8_general_ci agrupa como caracteres únicos como "s" e, presumivelmente, "e", respectivamente.

Em línguas não latinas, tais como idiomas asiáticos ou idiomas com alfabetos diferentes, utf8_unicode_ci pode ou não fazer diferença ou muita diferença dependendo do idioma.

Alguns caracteres Unicode são definidos como ignorável, o que significa que eles não devem contar para a ordem de classificação, e você deve passar para o próximo caractere em vez. utf8_unicode_ci lida com estes de forma adequada, que, por razões de desempenho utf8_general_ci não, e uma palavra com o carácter ignorável, serão classificados de forma diferente para uma palavra sem.

Se você quiser, você poderia usar utf8_general_ci maior parte do tempo, e só usar utf8_unicode_ci quando a classificação ia ser importante o suficiente para justificar o custo de desempenho.

Agora, no entanto, eu recomendo usar utf8_unicode_ci o tempo todo. No mundo real, o custo de desempenho vai ser irrisório (e se não for, você vai saber). E é melhor para o seu aplicativo para classificar corretamente em mais idiomas.

hasta!

terça-feira, 14 de agosto de 2012

Forçando atualizações contra vontade do Pagespeed


O PageSpeed, ferramenta muito útil que compacta e une arquivos estáticos( css, js, etc) às vezes atrapalha um pouco durante o desenvolvimento.

Depois de alguma alteração, e o envio da mesma no servidor, o antigo arquivo ainda é executado, devido ao cache desta ferramenta.

Para isso basta utilizar o filtro abaixo:



import os
from django import template
from django.utils import version
from django.conf import settings

register = template.Library()

@register.simple_tag
def revision_number():
    rev = version.get_svn_revision(settings.STATIC_PATH)
    return rev.split('-')[1]
Lembre-se de configurar o STATIC_PATH para o caminho de seus arquivos estáticos no settings.py.

E no html onde fizer a requisição do arquivo adcionar um parâmetro por GET para forçar uma nova atualização:
<script type="text/javascript" src="/static/site/js/js_all.js?v={% revision_number %}"></script>

<link rel="stylesheet" type="text/css" href="/static/site/style.css?v={% revision_number %}" media="all" />


hasta!