Quem sou eu

Minha foto

Formado em Computação, desenvolvedor web, interessado em tecnologia, metaleiro e um gamer inveterado.

Pesquisar

sexta-feira, 24 de maio de 2013

Como utilizar os inlines no front para os ModelForms (function based view)

Para isso é preciso de dois models, um model Pai que conterá N instancias de objetos de uma classe Filho, como por exemplo a relação de Conteúdo para Fotos. Assumindo este exemplo, deixe os arquivos como a seguir:

models.py
from django.db import models
# Create your models here.
class Conteudo(models.Model):
 """(Conteudo description)"""

 # ...
 # SEUS ATRIBUTOS AQUI
 # ...

 class Meta:
  verbose_name, verbose_name_plural = u"Conteúdo" , u"Conteúdos"


class Foto(models.Model):
 """(Foto description)"""
 conteudo= models.ForeignKey(Conteudo, verbose_name=u'Conteúdo')
 imagem = models.ImageField(upload_to="uploads/conteudos/imagem/%Y")

 class Meta:
  verbose_name, verbose_name_plural = u"Foto" , u"Fotos"
  ordering = ('id',)

 def __unicode__(self):
  return "%s" % str(self.imagem)

forms.py
from django.forms.models import inlineformset_factory
from models import Conteudo, Foto
class ConteudoForm(forms.ModelForm):
 class Meta:
  model = Conteudo

FotoFormSet = inlineformset_factory(Conteudo, Foto, extra=1)


views.py
from models import *
from django.shortcuts import render_to_response, get_object_or_404, redirect
from django.template import Context, loader, RequestContext
from django.core.context_processors import csrf
from forms import ConteudoForm, FotoFormSet

def conteudo_enviar(request):
 ret = ''
 if request.POST:
  c = {}
  c.update(csrf(request))

  r = request.POST
  f = request.FILES
  form = ConteudoForm(r,f)
  formset = FotoFormSet(r,f)

  if form.is_valid() and request.FILES:
   try:
    form.save()
    formset.instance = get_object_or_404(Conteudo, id=form.instance.id)
    formset.save()
    ret = u'Conteúdo enviado com sucesso.'

    # ZERANDO O FORM
    form = ConteudoForm()
    formset = FotoFormSet()

   except:
    ret = u'Erro ao enviar o conteúdo'
  elif request.FILES:
   for field in form:
    if field.errors:
     ret += "%s: %s" % (field.label, striptags(str(field.errors)) )
  else:
   ret += "Imagem: pelo menos uma imagem do conteúdo deve ser enviada"
 else:
  form = ConteudoForm()
  formset = FotoFormSet()

 VARS = {
  'form':form,
  'formset':formset,
  'ret':ret,
 }
 return render_to_response('conteudo_template.html', VARS, context_instance=RequestContext(request))

conteudo_template.html

<script type="text/javascript" src="http://underscorejs.org/underscore-min.js"></script>
<script type="text/html" id="foto-template">
 <div id="foto-<%= id %>" class="imagem">
  <input id="id_foto_set-<%= id %>-id" type="hidden" name="foto_set-<%= id %>-id">
     <label for="id_foto-<%= id %>-title">Imagem:</label>
     <input id="id_foto_set-<%= id %>-imagem" class="file" type="file" name="foto_set-<%= id %>-imagem">
     <input type="hidden" name="foto-<%= id %>-acao" id="id_foto-<%= id %>-acao">
     <input type="hidden" name="foto-<%= id %>-id" id="id_foto-<%= id %>-id">
     {% if not request.META.HTTP_USER_AGENT|isIE %}
   <div class="filename"></div>
   <div class="button-container">
   <input type="button" name="filebutton" class="filebutton" value="Procurar">
   </div>
  {% endif %}
  </div>
</script>

<script type="text/javascript">
jQuery(document).ready(function($) {
  // Stuff to do as soon as the DOM is ready;
  $('.add-foto').click(function(ev){
  ev.preventDefault();
  var count = $('.fotos').children().length;
  var tmplMarkup = $('#foto-template').html();
  var compiledTmpl = _.template(tmplMarkup, { id : count });
  $('div.fotos').append(compiledTmpl);
  // update form count
  $('#id_foto_set-TOTAL_FORMS').attr('value', count+1);
  console.log(count+1);
 });
});
</script>
{{ formset.management_form }}
<div class="fotos">
 {% for foto_form in formset %}
  <div id="foto-{{ forloop.counter0 }}" class="imagem">
   {{ foto_form.id }}
   {% if request.META.HTTP_USER_AGENT|isIE %}
    {# IE HACK PARA INPUT FILE #}
    {{ foto_form }}
    {# <input type="file" id="id_imagem" name="imagem[]" class="file" style="right:0; height: 50px; width:478px; position:absolute;opacity:1.0;filter:alpha(opacity=100);"> #}
   {% else %}
    {{ foto_form }}
    <div class="filename"></div>
    <div class="button-container">
     <input type="button" name="filebutton" class="filebutton" value="Procurar">
    </div>
   {% endif %}
  </div>
 {% endfor %}
</div>
<div class="form-actions">
  <button class="medium green add-foto">Adicionar mais fotos</button>
</div>

Para as class-based views, mostrarei como fazer no próximo post. hasta!