quinta-feira, 20 de dezembro de 2012

Como fazer o parse de um JSON em python

Como fazer o parse de um json para alimentar conteúdo ?

Na sua view que será responsável por buscar o conteúdo faça como abaixo:

def carga(request):
 import json
 from django.conf import settings

 json_data=open("%s/arquivo.json" % settings.MEDIA_ROOT).read()
 data = json.loads(json_data)

 retorno = ""

 for i in data['raiz']:
  retorno += "<h2>%s</h2>" % (i['titulo'],)

  for v in i['itens']:
   retorno += '--> %s: %s ' % (v['titulo'], v['valor'])
  retorno += '<hr>'

 return HttpResponse(retorno)

O exemplo acima retorna o conteúdo da seguinte forma:


Titulo1

--> Item titulo1: item valor1
--> Item titulo2: item valor2
--> Item titulo3: item valor3

Titulo2

--> Item titulo1: item valor1
--> Item titulo2: item valor2
--> Item titulo3: item valor3

Titulo3

--> Item titulo1: item valor1
--> Item titulo2: item valor2



hasta!

Como utilizar RSS de um site externo como fonte de conteúdo

Deseja colocar eu seu site o conteúdo de um RSS de um site externo?
Tarefa simples para o FeedParser (http://pypi.python.org/pypi/feedparser/)

Para tal, instale o FeedParser no seu ENV:
pip install feedparser

Na sua view que será responsável por buscar o conteúdo no site externo faça como abaixo:

def sua_view(request):
    import feedparser
    d = feedparser.parse('http://www.seu_site_externo.com.br/rss/')
    noticias = d['entries']
    VARS = {
        'noticias':noticias,
    }
    return render_to_response('noticias.html', VARS, context_instance=RequestContext(request))

E para acessar os conteúdos no template, utilize os dados conforme desejado, segue a lista dos atributos que o RSS retorna:
  • comments 
  • description
  • guidislink 
  • id
  • link 
  • links 
  • published 
  • published_parsed 
  • summary 
  • summary_detail 
  • tags 
  • title 
  • title_detail

hasta!

quarta-feira, 21 de novembro de 2012

Recuperando conteúdo de uma Tag HTML de uma URL

Recentemente precisei recuperar o conteúdo de uma tag html de uma URL para um propósito específico.

O Youtube, fez o favor de remover as famosas Tags dos vídeos de suas páginas, juntamente com o atributo de mesmo nome de sua API de integração. Com isso, não consegui mais peguar as tags para atualizar os vídeos de um projeto.

Percebi porém , que se procurasse no código fonte de cada página de vídeo, lá estavam a maioria, (senão todas) das tags no html <meta name="keywords">. Motivo pelo qual acredito que ainda esteja lá seria por busca e indexação dos vídeos.

Para recuperá-las, procurei algum pacote do python para fazer o parse do html e me deparei com o
Beautiful Soup. Ele pode ser instalado com o comando dentro do seu ENV:

pip install BeautifulSoup

E também possui uma documentação bem completa no link: http://www.crummy.com/software/BeautifulSoup/bs3/documentation.html

Criei uma def para fazer o trabalho, vamos a ela:


def get_tags(youtube_id):

	response = urllib2.urlopen('http://www.youtube.com/watch?v=%s' % youtube_id )
	html = str( response.read() )

	xmlSoup = BeautifulStoneSoup(html)

	tags = xmlSoup.findAll(attrs={"name" : "keywords"})[0]
	tags = str(tags)
	tags = tags.replace('\n','')

	return tags


Será retornado uma string com o conteúdo da tag meta keywords, sendo possível fazer todos os tratamentos necessários, como transformar em uma tupla, inserir no banco, etc.

Para outras tags, recomendo uma olhada na documentação do BeautifulSoup, pois tem várias formas de encontrar o que deseja.

hasta!

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!

segunda-feira, 2 de julho de 2012

Como criar um decorator


Decorators são muito úteis quando se precisa de certas condições antes da execução de determinadas views, como por exemplo, views que obrigam o usuário estar logado para ter acesso, tais como Meus Pedidos, Meu Painel,  etc.
Para isso utiliza-se o decorator login_required, disponível no pacote django.contrib.auth.decorators. Basta adicioná-lo antes da view desejada da seguinte forma:

@login_required
def sua_view(request):
     #seu código aqui
Também é possível criar decorators personalizados, para verificar certas situações, como preenchimento completo de algum cadastro, se o cliente está com a assinatura de conteúdo em dia, etc. Para criar um decorator, basta fazê-lo da como mostra o exemplo abaixo, em qualquer arquivo ".py". Recomendo criar um arquivo separado para isso.

Exemplo:

Crie um arquivo admin.py na raiz do seu projeto com o seguinte conteúdo:
def nome_decorator(f):
     def verifica(request, *args, **kwargs):
          if <CONDICAO DE FALHA A SER TESTADA>
               # INTERROMPE O FLUXO NORMAL E NÃO EXECUTA A VIEW ASSOCIADA
          else:
               # CONDICAO DE SUCESSO, RETORNA AO FLUXO NORMAL
               return f(request, *args, **kwargs)
     verifica.__doc__= f.__doc__
     verifica.__name__= f.__name__
     return verifica

Em seu arquivo views.py, onde existe a view a ser associada ao decorator utilize:

from admin import nome_decorator

@nome_decorator
def sua_view(request):
     #seu código aqui
Fique atento para o caminho da importação do decorator, dependendo de onde salvar, pode ser que haja alteração a ser feita na linha de import.


Pode ser que precise de 2 decorators para uma mesma view como no exemplo abaixo:



@login_required
@nome_decorator
def sua_view(request):
     #seu código aqui


Para estes casos, as validações se darão na ordem que forem colocados os decorators, de cima pra baixo, ou seja, para o exemplo acima, primeiro será avaliado se o visitante está logado para depois verificar as condições colocadas no decorator personalizado que foi criado.


hasta!

sexta-feira, 18 de maio de 2012

Sublime Text 2: Meu (provavelmente) Último Editor

A tempos procurava um editor com recursos interessantes para aumentar a produtividade. Tomei conhecimento do TextMate do Mac e muito me interesssei. No ambiente de trabalho por ser Windows ( triste, eu sei ), buscava algo similar. Foi quando conheci o Intype (http://inotai.com/intype/) e encontrei na net boas almas que converteram os bundles do TextMate para o Intype.
No Intype, acabei utilizando todos os bundles que haviam disponíveis e foi uma experiencia satisfatória. A questão é que o intype se tornará pago cedo ou tarde, então outra alternativa precisava ser encontrada.



Eis que surge o Sublime Text 2 (http://www.sublimetext.com/). Com versões gratuita e paga, ele supera todos os editores que já trabalhei. Possui vários recursos interessantes, tais como:
  • Highlighting para várias linguagens como C, C++, C#, CSS, D, Erlang, HTML, Groovy, Haskell, HTML, Java, JavaScript, LaTeX, Lisp, Lua, Markdown, Matlab, OCaml, Perl, PHP, Python, R, Ruby, SQL, TCL, Textile e XML e mais para download 
  • Modo Full Screen (F11) com recurso Distraction Free (Shift + F11) 
  • Scroll com o minimap do código 
  • Auto save, jamais perca algo. 
  • Vários temas disponíveis, particularmente prefiro o Monokai 
  • Somente modo texto. Sem frescura. 
  • Seleção múltipla 
  • Busca incremental durante a digitação 
  • Seleção em coluna 
  • Mantém o case durante o replace 
  • Busca e substituição por expressão regular 
  • Auto complete 
  • Snippets e Pacotes que otimizam o tempo (e viciam) durante o uso. 
  • e muitos outros. 
Os Pacotes e Snippets, merecem uma descrição a parte. Primeiramente instale o Package Control seguindo esse tutorial. Com ele será possível instalar vários pacotes com os mais diversos recursos para melhorar sua produtividade. Alguns interessantes:
  • Alignment
  • SideBarEnhancements
  • JQuery
  • HTML5
  • e muitos outros disponíveis, basta dar uma olhada no Package Control. 
Estou utilizando estes aqui:


O mais interessantes do esquema do  Package Control, é que tudo é feito diretamente pelo Sublime, sem burocracia de download, instalação, etc. 

Os Snippets são os mais utilizados, na minha opinião. Da mesma forma que no TextMate, o Sublime completa trechos de códigos pré-configurados após a digitação de um termo (gatilho, vulgo tab trigger) e pressionar a tecla Tab. O mais interessante é que é possível editar e criar novos de uma maneira bem fácil. Basta ir pelo menu Tools >> New Snippet. O exemplo fornecido é muito óbvio, mas vamos a ele:


<snippet>

<content><![CDATA[

Hello, ${1:this} is a ${2:snippet}.

]]></content>

<!-- Optional: Set a tabTrigger to define how to trigger the snippet -->
<!-- <tabTrigger>hello</tabTrigger> -->
<!-- Optional: Set a scope to limit where the snippet will trigger -->
<!-- <scope>source.python</scope> -->

</snippet>


Todos os termos começados com $, seguido de um número são os parâmetros editáveis do bloco inserido pelo Sublime, descrito no content, possuindo navegação através do Tab, de acordo com a ordem numérica. O valor seguido dos ":"  são os valores padrões para cada parâmetro inserido. Descomente a linha do tabTrigger e digite o gatilho de sua preferência.

Além da possibilidade de criar novos snippets, é possivel importar  todos os bundles do TextMate com uma simples operação de ctrl + c , ctrc + v ( sim, simplesmente colar os arquivos) para a pasta do Sublime. Ele se encarrega de fazer funcionar. Única alteração é que quando copiar os arquivos .tmbundle para o Windows, eles virão como se fosse um pasta com essa extensão. Retire a extensão e salve essas pastas em:
C:\Users\<USUARIO DA MAQUINA>\AppData\Roaming\Sublime Text 2\Packages (Windows)
<USUARIO DA MAQUINA>/Biblioteca/Application Suport/Sublime Text 2/Packages (MAC)

Com isso, será disponibilizado os pacotes no canto inferior direito do Sublime.

Com uma interface amigável, vários recursos fantásticos e leve, o Sublime Text 2 tem se mostrado com o melhor editor que já trabalhei. Disponível para Windows, Linux e Mac, possibilita uma interface única para quem, como eu trabalha em ambientes diferentes.


Lista de Comandos – Mac
Navegar entre os arquivos: Command + P
Layout de 2 colunas: Command + Option + 2
Modo de distração livre: Command + Option + Shift + F
Find: Command + F
Find / Replace: Command + Option + F
Find / Where / Replace: Command + Shift + F
Indentação à esquerda: Command + [ ou Shift + Tab
Indentação à direita: Command + ] ou Tab
Comentário: Command + /
Multi-select: Command pressionado + Clique em várias linhas
Code Folding – Minimiza Bloco: Command + Option + [
Code Folding - Maximiza Bloco: Command + Option + ]
Code Folding – Minimiza Atributos: Command + K + Command + T
Code Folding – Maximiza Atributos: Command + K + Command + 0
Console: Ctrl + `
Menu: Command + Shift + P
Haiku: Ctrl + Option + Enter
Prefixr: Command + Ctrl + X
JSHint: Ctrl + J
JSMinifier: Ctrl + Option + M

Lista de Comandos – Windows/Linux
Navegar entre os arquivos: Ctrl + P
Layout de 2 colunas: Alt + Shift + 2
Modo de distração livre: Shift + F11
Find: Ctrl + F
Find / Replace: Ctrl + H
Find / Where / Replace: Ctrl + Shift + H
Indentação à esquerda: Ctrl + [
Indentação à direita: Ctrl + ]
Comentário: Ctrl + / ou Ctrl+;
Multi-select: Ctrl pressionado + Clique em várias linhas
Code Folding – Minimiza Bloco: Ctrl + Shift + [
Code Folding - Maximiza Bloco: Ctrl + Shift + ]
Code Folding – Minimiza Atributos: Ctrl + K + Ctrl + J
Code Folding – Maximiza Atributos: Ctrl + K + Ctrl + 1
Console: Ctrl + `
Menu: Ctrl + Shift + P
Haiku: Ctrl + Alt + Enter
Prefixr: Ctrl + Alt + X
JSHint: Ctrl + J
JSMinifier: Ctrl + Alt + M

Bônus
Deletar linha: Ctrl + Shift + K (Windows/Mac/Linux)
Duplicar linha – Mac – Command + Shift + D – Windows/Linux – Ctrl + Shift + D
Troca de linhas: Mac – Command + Ctrl + Seta (cima ou baixo) – Windows/Linux – Ctrl + Shift + Seta (cima ou baixo)

E mais
Jade – Syntax Highlight – https://github.com/miksago/jade-tmbundle
Stylus – Syntax Highlight – https://github.com/LearnBoost/stylus
JSHint – https://github.com/uipoet/sublime-jshint


Algumas configurações interessantes para se colocar no Preferences > Settings - User:

{
     "bold_folder_labels": true,
    "color_scheme": "Packages/Color Scheme - Default/Monokai.tmTheme",
    "font_face": "Monaco",
    "font_size": 13,
    "highlight_line": true,
    "ignored_packages":["Vintage"],
    "rulers": [72],
    "scroll_past_end": true,
    "shift_tab_unindent": false,
    "theme": "Soda Dark.sublime-theme",
    "trim_trailing_white_space_on_save": false,
    "trim_trailing_white_space_on_save": true,
}


Façam download e experimentem. Vale a pena.
Hasta!


sexta-feira, 10 de fevereiro de 2012

Instalação do Vagrant no windows


Precisa de um ambiente que simule o servidor onde fará o deploy do projeto? Cansado de lidar com as diferenças entre sistemas operacionais, versões etc?

Esta semana tive a oportunidade de conhecer o Vagrant. Um sistema que trabalha com a API do Virtual Box. Nele é possível de uma maneira fácil criar uma máquina virtual com as características que precisar para simular o ambiente online.

O tutorial abaixo mostra um resumo do que li a respeito para  criar uma VM com Ubuntu, python2.6, virtualenv, etc.

  1. Baixe e instale a Oracle VM Virtual Box (https://www.virtualbox.org/wiki/Downloads
  2. Baixe e instale o Ruby (http://rubyinstaller.org/downloads/
  3. Baixe o Development Kit (http://rubyinstaller.org/downloads/
    1. Installation Instructions (https://github.com/oneclick/rubyinstaller/wiki/Development-Kit
      1. While installation is (in general) simple, please ensure you carefully follow each step below. 
      2. Preparation 
      3. If you previously installed the legacy DevKit devkit-3.4.5r3-20091110.7z, its artifacts were extracted into each Ruby installation and need to be manually removed. Remove the gcc.bat, make.bat, and sh.bat stub batch files in <RUBY_INSTALL_DIR>\bin and the <RUBY_INSTALL_DIR>\devkit subdirectory for each Ruby installation using the legacy DevKit. 
      4. If you previously installed one of the legacy self-extracting DevKit’s, follow the SFX DevKit upgrade instructions. 
    2. Download Files 
      1. The current DevKit is available at the RubyInstaller download page with older versions available at the archives page. As backup, check our GitHub downloads page. 
    3. Extract Files 
      1. Left double-click the self-extracting executable (SFX) downloaded from Step 2 and choose a directory (without spaces) to install the DevKit artifacts into. For example, C:\DevKit. NOTE: the SFX is really a 7-Zip archive with a bit of embedded magic. If you already have 7-Zip installed, you can simply right-click it and extract it’s contents as you would a normal 7z archive. In the instructions that follow, the directory that you selected is identified as <DEVKIT_INSTALL_DIR>. 
    4. Run Installation Scripts 
      1. cd <DEVKIT_INSTALL_DIR> from Step 3 above. 
      2. ruby dk.rb init to generate the config.yml file to be used later in this Step. Your installed Rubies will be listed there (only those installed by a RubyInstaller package are detected at present). 
      3. edit the generated config.yml file to include installed Rubies not automagically discovered or remove Rubies you do not want to use the DevKit with. 
      4. [optional] ruby dk.rb review to review the list of Rubies to be enhanced to use the DevKit and verify the changes you made to it are correct. 
      5. finally, ruby dk.rb install to DevKit enhance your installed Rubies. This step installs (or updates) an operating_system.rb file into the relevant directory needed to implement a RubyGems pre_install hook and a devkit.rb helper library file into <RUBY_INSTALL_DIR>\lib\ruby\site_ruby. NOTE: you may need to use the --force option to update (with backup of the originals) the above mentioned files as discussed at the SFX DevKit upgrade FAQ entry. 
    5. Test Installation 
  4. Confirm your Ruby environment is correctly using the DevKit by running gem install rdiscount --platform=ruby. RDiscount should install correctly and you should see Temporarily enhancing PATH to include DevKit... in the screen messages. Next run ruby -rubygems -e "require 'rdiscount'; puts RDiscount.new('**Hello RubyInstaller**').to_html" to confirm that the rdiscount gem is working. 
  5. Adicione o caminho da pasta bin do ruby da instalção feita no Path. Ex. C:\Ruby193\bin 
  6. Execute o comando: gem install vagrant 
  7. Antes de criar sua maquina, crie uma pasta para abrigar os arquivos de configuraçao: 
    1. mkdir vagrant-machine 
    2. cd vagrant-machine 
    3. vagrant box add lucid32 http://files.vagrantup.com/lucid32.box
    4. vagrant init lucid32 
    5. vagrant up 
    6. Acesse via ssh a maquina virtual: 
    7. pelo putty, conecte em vagrant@127.0.0.1 na porta 2222, com a senha vagrant 
  8. Instale os pacotes de desenvolvimento: 
    1. sudo apt-get install python2.6 python2.6-dev libxml2-dev libxslt1-dev python-libxml2 python-setuptools git-core build-essential libxml2-dev libpcre3-dev libpcrecpp0 libssl-dev zlib1g-dev libgeoip-dev memcached libmemcached-dev python-mysqldb libmysqlclient16-dev python-virtualenv 
    2. Se por ventura der algo errado, tente o mesmo comando acima mas adicione no fim o --fix-missing
  9. É necessário a instalação de alguns pacotes para tudo funcionar perfeitamente, além dos acima. Execute os comandos abaixo, caso não instalar como comando acima:
    1. sudo apt-get update
    2. sudo apt-get install mysql-client
    3. sudo apt-get install libmysqlclient16-dev
    4. sudo apt-get install python-virtualenv
    5. sudo apt-get build-dep python-imaging
  10. Vá até a home do usuário e rode o comando abaixo para atualizar o apt-get e outros pacotes: 
    1. sudo sh postinstall.sh
    2. Vá no VagrantFile no diretorio que instalou o passo 6.a e edite. 
    3. Descomente a linha: # config.vm.forward_port 80, 8080 e configure para as portas que deseja utilizar no windows quando rodar os projetos. Ex: 
      1. config.vm.forward_port 8000, 8000 
      2. # config.vm.forward_port 9000, 9000
  11. Reinicie o Vagrant com o comando: vagrant reload no seu prompt do windows

O tutorial acima funciona e estou utilizando-o a muito tempo. Depois de um tempo, apareceu a seguinte mensagem:
New release 'precise' available.
Run 'do-release-upgrade' to upgrade to it.

Tentei atualizar e tive problemas. Perdeu-se o compartilhamento da pasta com o Windows, bem como problemas para instalação dos pacotes PIL e MySQL-python.

Resolvi com a reinstalação do começo, sem fazer esta atualização.

hasta!

terça-feira, 7 de fevereiro de 2012

Filtrar apenas os usuários staff no admin

Quando utilizamos a autenticação provida pelo django, um problema é que sempre que entramos no change list do Auth User, lá tem todos os usuários que podem fazer login, tanto no front quanto no admin.

Para isso basta colocar o código abaixo em qualquer arquivo admin.py:


from django.contrib import admin
from django.contrib.auth.admin import UserAdmin
from django.contrib.auth.models import User

class StaffAdmin(UserAdmin):
"""
Esta classe recria as propriedades do admin do model auth.User
"""
list_filter = ( 'is_active', 'is_superuser' )
date_hierarchy = 'date_joined'
save_on_top = True

def queryset(self, request):
qs = super( UserAdmin, self ).queryset( request )
qs = qs.exclude( is_staff=False )
return qs


admin.site.unregister( User )
admin.site.register( User, StaffAdmin )


Se ainda preferir deixar separado, pode criar um arquivo admin.py na raiz do projeto e incluir o nome da pasta ( fornecido no startproject ) no INSTALLED_APPS.

hasta!