Bem, é esse tipo de miudagem que vou listar neste post. Para montá-lo fui adicionando a ele todas as miudagens de que precisei várias nos últimos tempos e acabei tendo de pesquisar de novo para relembrar como fazer. Tem mais algumas que adicionei por serem coisas miúdas, mas difíceis de encontrar a solução por aí.
Exibir o conteúdo de uma variável como html puro
Esta dica é bem simples. Sabe quando você tem um conteúdo dentro uma variável que você gostaria que fosse interpretado como html na página e quando você faz um {{var_exemplo}} é dado um escape em todo o conteúdo e caracteres como "<" se tornam "<"?
Esse é o comportamento padrão do django. Por padrão ele vai exibir o conteúdo das variáveis como texto ou como números e dá escape nos caracteres especiais como os sinais de maior e menor para garantir que serão exibidos corretamente em sua página. Além das questões de segurança envolvidas no caso.
Como resolver esse problema? Muito simples! Use a template tag safe. Ao invés de fazer somente {{var_exemplo}} faça {{var_exemplo|safe}} e todo o conteúdo dela será tratado como html.
Ocultar um campo no admin (tanto ficar oculto quanto não ser usado):
Já precisou criar algum campo que só é usado pelo seu sistema interno e que não deveria por nada aparecer no admin do django? Eu já para armazenar permalinks. E como o campo ficou lá visível é claro que o usuário alterou o conteúdo dele e reclamou dos resultados horrendos. Claro! Ele jurava que não tinha feito nada.
Para evitar esse tipo de situação, uma coisa bem simples de se fazer, que é aceita por todos os campos dos models do django, é adicionar o seguinte parâmetro nos campos a ocultar:
Prontinho! O seu campo agora é um campo "não editável" e não será exibido no painel de administração.
Agora, se você quer um campo oculto para armazenar a data de criação do objeto:
Ou, se for um campo para salvar a data da última alteração do objeto:
Fonte: http://stackoverflow.com/questions/6752182/how-to-hide-model-field-in-django-admin
Fontes: http://stackoverflow.com/questions/4694767/overriding-djangos-relatedmanager-methods e
https://docs.djangoproject.com/en/1.2/topics/db/managers/
Esta parte do código deve ser colocada no local onde você quiser que a caixa de comentários apareça:
Não se esqueça de alterar o valor de data-href para as urls das páginas do seu site em que você vai colocar ao invés de http://example.com.Para evitar esse tipo de situação, uma coisa bem simples de se fazer, que é aceita por todos os campos dos models do django, é adicionar o seguinte parâmetro nos campos a ocultar:
campo_exemplo = models.IntegerField(editable=False)
Prontinho! O seu campo agora é um campo "não editável" e não será exibido no painel de administração.
Agora, se você quer um campo oculto para armazenar a data de criação do objeto:
campo_exemplo = models.DateTimeField(auto_now=True)
Ou, se for um campo para salvar a data da última alteração do objeto:
campo_exemplo = models.DateTimeField(auto_now_add=True)
Fonte: http://stackoverflow.com/questions/6752182/how-to-hide-model-field-in-django-admin
Object managers
Quando vamos fazer consultas sobre objetos do django temos que usar métodos como all, filter, get, etc. Algumas vezes gostaríamos de ter nossos próprios para facilitar nossa vida. Por exemplo, o comportamento do método get: lança exceção se não encontrar nenhum objeto ou se encontrar mais que um. Poderíamos querer, por exemplo, um método get_or_none. Um método que retorne None quando não encontrar nada, ao invés de uma exceção.
Esse método do exemplo é possível, e qualquer um outro que você quiser. Basta aprender a utilizar os object managers. Eles são utilizados por todos os models do django e podem ser sobrescritos.
Veja um exemplo:
Note que há um atributo objects no model ao qual o manager criado foi atribuído. Com isso novos métodos serão adicionados ao model. No caso do exemplo teríamos: Exemplo.objects.get_or_none()Veja um exemplo:
class ManagerExemplo(models.Manager): def get_or_none(self): try:
aux = super(OrganizationManager,self).get_query_set() len(aux) #faz o django executar a consulta de fato return aux except: return None class Exemplo(models.Model): campoqualquer = models.CharField(max_length=100) objects = ManagerExemplo()
Fontes: http://stackoverflow.com/questions/4694767/overriding-djangos-relatedmanager-methods e
https://docs.djangoproject.com/en/1.2/topics/db/managers/
Integração com comentários do facebook
Este é bem simples, mas já usei algumas vezes já e acho que vale a pena colocar aqui. Você terá que criar uma aplicação no facebook nesta página aqui. É só entrar no link e clicar no botão a direita para criar a aplicação. Depois você entra nesta página aqui e vai obter um código similar com o código abaixo:<script>(function(d, s, id) { var js, fjs = d.getElementsByTagName(s)[0]; if (d.getElementById(id)) return; js = d.createElement(s); js.id = id; js.src = "//connect.facebook.net/en_US/all.js#xfbml=1&appId=ID_DO_SEU_APP"; fjs.parentNode.insertBefore(js, fjs); }(document, 'script', 'facebook-jssdk'));</script>A única coisa que falta nele é o ID_DO_SEU_APP. Ou melhor, substitua esse texto pelo id da sua aplicação no facebook. Se você pegar o código pelo link acima, ele já estará ajustado para a sua aplicação. Essa parte do código você coloca no cabeçalho da sua página.
Esta parte do código deve ser colocada no local onde você quiser que a caixa de comentários apareça:
<div class="fb-comments" data-href="http://example.com" data-num-posts="2" data-width="470"></div>
Fontes: http://stackoverflow.com/questions/10638503/django-facebook-comments-integration
Usar ManyToManyField como Inline
Estou desenvolvendo um sistema em que precisei criar relações de muitos para muitos entre dois modelos. Para ajudar um bocado, essa relação teve que ser criada manualmente, pois há atributos associados a ela. E agora? Sem os atributos associados o objeto é exibido normalmente no admin como um select múltiplo. Mas isso não funciona mais. O que fazer?
É até que simples quando vemos a solução.
No models.py:
É até que simples quando vemos a solução.
No models.py:
class Planta(models.Model): accepts = models.ManyToManyField('self', symmetrical=False, null=True, blank=True, through="planta.Aceita", related_name="aceita") class Aceita(models.Model): a_planta = models.ForeignKey(Planta, related_name="a_planta") favorecida_por = models.ForeignKey(Planta, related_name="favorecida_por") intensidade = models.IntegerField(null=True, blank=True, choices=ACEITA_OPCOES_INTENSIDADE, default=0) descricao = models.CharField(max_length=255, null=True, blank=True)
Aqui já temos como definir uma relação assimétrica entre objetos do mesmo tipo por meio de uma relação de muitos para muitos definida manualmente em um segundo model com atributos extras.
Até aqui tranquilo. Praticamente tudo era, de certa forma, fácil de encontrar na net. E como fazer para o ManyToManyField ser usado como uma ForeignKey?
Essa parte é resolvida no admin.py:
Pronto! Já temos tudo funcionando. Note que o fk_name indica qual ForeignKey vai ser usada enquanto que o model está indicando para usar o model intermediário especificado no parâmetro through do campo ManyToManyField.
Fontes: http://stackoverflow.com/questions/3153026/django-1-2-1-inline-admin-for-many-to-many-fields,
http://stackoverflow.com/questions/2408989/more-than-1-foreign-key, https://docs.djangoproject.com/en/dev/topics/db/models/#extra-fields-on-many-to-many-relationships, https://docs.djangoproject.com/en/dev/ref/models/fields/#django.db.models.ManyToManyField e https://docs.djangoproject.com/en/dev/topics/db/examples/many_to_many/.class AceitaInline(admin.TabularInline): model = Planta.accepts.through fk_name = 'a_planta' class PlantaAdmin(admin.ModelAdmin): inlines = [AceitaInline,]
Pronto! Já temos tudo funcionando. Note que o fk_name indica qual ForeignKey vai ser usada enquanto que o model está indicando para usar o model intermediário especificado no parâmetro through do campo ManyToManyField.
Como deixar todos os campos de múltipla escolha com o estilo do admin
O estilo dos selects para mais de uma opção do admin do django é bem legal. Mas quando criamos os nossos modelos de administração o django não o usa. Usa o select box normalzinho. Existem várias formas de resolver isso. Você pode colocar um script no template da página e fazê-lo estilizar os selects que você quiser, pode utilizar um form e fazer a estilização como widget. Ou, a solução que prefiro e vou mostrar aqui por ser bem mais simples, prática e menos intrusiva. Basta adicionar o atributo formfield_overrides com o seguinte valor ao seu model de admin, que TODOS os selects de múltipla escolha dele serão estilizados automaticamente.class PlantaAdmin(admin.ModelAdmin): inlines = [AceitaInline, ] formfield_overrides = {models.ManyToManyField: {'widget': FilteredSelectMultiple("verbose name", is_stacked=False)},}
Pronto! Tudo em ordem. ;)
Fontes: http://stackoverflow.com/questions/1698435/django-multi-select-widget
Domínio estranho
Sabe quando você usa o password_reset do Django e o endereço base das urls no email enviado vai para todos com o domínio igual a "www.example.com" e você não acha em lugar nenhum como resolver isso? Então, é bem simples. Esse endereço é obtido a partir do módulo sites do django(django.contrib.sites). Para alterá-lo, basta fazer isto:from django.contrib.sites.models import Site obj=Site.objects.get(id=1) #ou Site.objects.get_current() caso esteja usando vários sites obj.name='Meu site' obj.domain='www.meusite.com.br' obj.save()
Ou então, vá no admin do seu projeto, na guia Sites e mude o endereço do que estiver lá para o que você quiser. ;)
Paginação
Paginação é algo simples de fazer, mas sempre dá problemas quando vamos fazer "na mão". Além de demorar mais. Para resolver isso, há um módulo do django chamado Paginator. Ele cuida dessas questões e é fácil de usá-lo:
from django.core.paginator import Paginator objects = ['john', 'paul', 'george', 'ringo'] p = Paginator(objects, 2) #recebe a lista, queryset, dicionario, etc e o numero de objetos por página p.num_pages #retorna o numero de paginas: 2 p.page_range #retorna uma lista com indice de todas as paginas: [1, 2] page1 = p.page(1) #retorna um objeto Page para a primeira pagina page1.object_list #retorna a lista de objetos desta pagina: ['john', 'paul'] page2.has_next() #verifica se ha uma proxima pagina ou nao page2.has_previous() #verifica se ha uma pagina anterior ou nao page2.has_other_pages() #verifica se ha uma pagina anterior ou proxima page2.next_page_number() #retorna o indice da proxima pagina page2.previous_page_number() #retorna o indice da pagina anterior page2.start_index() #o indice iniciado em 1 do primeiro item desta pagina page2.end_index() #o indice iniciado em 1 do ultimo item desta pagina p.page(0) #erro: o indice deve ser maior que 0 p.page(3) #erro: a pagina de indice 3 esta vazia
Bem, sabendo desses métodos, acho que já é mais que o suficiente para usá-lo, não é mesmo?
Se não, me avise. Que edito e acrescento um exemplo mais completo. ;)
Até a próxima!
Um comentário:
valeu mano ajudou pra caramba
Postar um comentário