Modificando RadioSelect na renderização

oraculum

Tagged: ,


Esses dias precisei de modificar a exibição de um radio select na template do Projeto Galileu, bem por causa do css do template, por default o framework django monta assim as suas RadioSelect:

1
2
3
4
5
6
7
8
<ul>
<li>
<label for="id_tipo_0"><input checked="checked" name="tipo" value="1" id="id_tipo_0" type="radio" class="required" /> Despesa</label>
</li>
<li>
<label for="id_tipo_1"><input value="2" type="radio" class="required" name="tipo" id="id_tipo_1" /> Receita</label>
</li>
</ul>

Acontece que eu preciso de remover essas tags (

    e
  • ) na hora da renderização, depois de apanhar um pouquinho pela net consegui achar a solução, segue-se os códigos abaixo de como fazer:

    Meu forms.py:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    
    # aqui importamos o radiofieldrenderer que será usado para customizarmos nossa renderização
    from django.forms.widgets import RadioFieldRenderer
    # importamos esse utilitário pois sem ele os campos são exibidos como String no HTML ou seja ele não apareceram como radio próriamente dito mais sim escritos o código em string, aff deixe pra lá se queiser ver como é mande retornar sem essa função :)
    from django.utils.safestring import mark_safe
     
    # sem comentarios aqui você já deve saber o que é isso
    Tipo_Choices = (
                    ('1',  'Despesa'), 
                    ('2',  'Receita'), 
        )
     
    # aqui é a classe que vamos customizar nossa renderização
    class MyRenderer(RadioFieldRenderer):
        def render(self):
            # essa função retorna o nosso radio sem as UL e LI mas aqui você pode fazer outras customizações basta apenas inserir o que quiser aqui, veja abaixo um exemplo usando <br> 
            # return mark_safe(u'<br />\n'.join([unicode(choice) for choice in self]))
            # entendeu o sentido da coisa ? bem aqui vou deixar por tua conta então faça o que achar melhor :)
            return mark_safe(u'\n%s\n' % u'\n'.join([u'%s' % w for w in self]))
     
    class PlanoContaForm(ModelForm):
        id = IntegerField(required=False,widget=HiddenInput())
        username = IntegerField(required=True,  widget=HiddenInput())
        # aqui só fique atento para a parte do renderer=MyRenderer que você deve declara a classe que você criou acima o resto é basicão
        tipo = ChoiceField(widget=RadioSelect(attrs={'class':'required'},  renderer=MyRenderer),  choices=Tipo_Choices,  initial="1")
        nome = CharField(widget=TextInput(attrs={'class':'textInput required'}), required=True)

    Para o Html declare o field normalmente apenas fazendo {{ field }}, apenas um exemplo de como está o meu template:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    
    {% for field in form %}
    	{% ifequal field.html_name "tipo" %}
    	<div class="ctrlHolder">
    		<p class="label">Tipo</p>
    		<div class="multiField">
    		  {{ field }}
    		</div>
    	</div>
    	{% else %}
    	<div class="ctrlHolder">
    		  {% if not field.is_hidden %}
    				{{field.label_tag}}
    		  {% endif %}
    		  {{field}}
    	</div>
    	{% endifequal %}
    {% endfor %}

    Essa classe renderer serve para outros tipos de widgets como Select, MultipleSelect, etc é só dar uma pequena adaptada.

    Já tava me esquecendo o resultado disso aí tudo acima fica assim:

    1
    2
    
    <label for="id_tipo_0"><input checked="checked" name="tipo" value="1" id="id_tipo_0" type="radio" class="blockLabel" /> Despesa</label>
    <label for="id_tipo_1"><input value="2" type="radio" class="blockLabel" name="tipo" id="id_tipo_1" /> Receita</label>
    Share Button

Leave a Reply