quarta-feira, 20 de abril de 2016

Como esconder alguns registros do changelist do admin do Django



A pergunta é simples: Pra que eu um dia iria precisar esconder alguns registros do change list, se já estou no admin como superuser?

Bom, imagine que seu cliente quer o acesso ao admin para gerenciar os conteúdos e também acesso a alguma seção do projeto que o login é necessário.

Quão surpreso você ficaria se descobrisse, que aquele seu cadastro de teste onde vc conseguia entrar para ajudar, testar e acompanhar o andamento do projeto fosse removido?

Isso, apesar de ridículo, não é de todo o impossível, e foi por passar por algo semelhante que escrevo este post.


Para ocultar os registros de uma determinada classe, basta  sobrescrever o método get_queryset do admin daquela classe no admin.py:

class CadastroAdmin(admin.ModelAdmin):
 form = CadastroForm
 search_fields = ('nome',)
 list_display = ('nome', 'email', 'unidade','ativo',)
 list_filter = ['ativo','unidade']
 list_editable = ['ativo',]
 exclude = ('user',)
 save_on_top = True


 def get_queryset(self, request):
  qs = super(CadastroAdmin, self).get_queryset(request)
  if request.user.is_superuser:
   return qs
  return qs.exclude(id__in=[13,14,15])

admin.site.register(Cadastro, CadastroAdmin)

No exemplo acima, quando o usuário logado for superuser do admin, este verá todos os registros, do contrário, a queryset excluirá dos resultados os cadastros com ids 13, 14 e 15.

Com pequenos ajustes, este método tornar bastante útil para evitar dedos inquietos clicando onde não devem.


hasta!

sexta-feira, 8 de abril de 2016

SyntaxError: expected expression, got '<' /admin/jsi18n/ (line 1) interpolate is not defined

SyntaxError: expected expression, got '<'  <!DOCTYPE html> /admin/jsi18n/ (line 1) 
interpolate is not defined

Esse erro apareceu quando fiz a utilização do SelectFilter2 para um form no front.

Ele é responsável pela ferramenta de filter_horizontal / filter_vertical do admin, e deveria ser exibido assim:




E com o erro era exibido assim:





Para resolver esse problema:


Adicione no seu urls.py:
...
url(r'^jsi18n/$', 'django.views.i18n.javascript_catalog'),
...


E no seu template que for utilzar o widget:

<script type="text/javascript" src="/jsi18n/" > </script>

segunda-feira, 1 de fevereiro de 2016

Como utilizar o "Salvar e adicionar outro" do Admin no Front com Class-Based Views

O botão de Salvar e Adicionar outro é muito útil no administrativo quando se faz necessário inserir uma lista de dados em algum modelo.

No front, quando o usuário tem permissão de inserir algo para persistir o banco, também é possível utilizar este recurso. Vejamos como:

views.py

class SuaClasseCreateView(CreateView):
	form_class = SuaClasseForm
	success_url = '/url-de-sucesso/'
	template_name = 'form.html'
	model = SuaClasse

	def post(self, request, *args, **kwargs):

		form_class = self.get_form_class()
		form = self.get_form(form_class)

		if form.is_valid():

			if request.POST.get('_addanother'):
				self.success_url = '/url-de-nova-insercao/'

			return self.form_valid(form)
		else:
			return self.form_invalid(form)


	def form_valid(self, form):
		form.save()
		return HttpResponseRedirect(self.success_url)

	def form_invalid(self, form):
		return self.render_to_response(
			self.get_context_data(form=form)
		)



class SuaClasseUpdateView(UpdateView):
	form_class = SuaClasseForm
	model = SuaClasse
	success_url = '/url-de-sucesso/'
	template_name = 'form.html'


	def post(self, request, *args, **kwargs):
		self.object = self.get_object()
		form_class = self.get_form_class()
		form = self.get_form(form_class)
		form.instance = self.object

		if form.is_valid():

			if request.POST.get('_addanother'):
				self.success_url = '/url-de-nova-insercao/'

			return self.form_valid(form)
		else:
			return self.form_invalid(form)


	def form_valid(self, form):
		form.save()
		return HttpResponseRedirect(self.success_url)

	def form_invalid(self, form):
		return self.render_to_response(
			self.get_context_data(form=form)
		)

As views acima funcionam para qualquer modelo, sem nenhuma alteração nos forms.py. No html, apenas é necessário incluir o botão de Salvar e adicionar outro como exemplo abaixo:

form.html
<input type="submit" name="_addanother" value="Salvar e adicionar outro(a)">


Quando o clique é feito neste botão, o value dele é enviado via post, e a tratativa disso está no método post da view. Quando não é clicado, o valor não é enviado, não redirecionando assim para uma nova tela com o formulário aberto.

hasta!