Mostrando entradas con la etiqueta file uploading. Mostrar todas las entradas
Mostrando entradas con la etiqueta file uploading. Mostrar todas las entradas

viernes, 29 de abril de 2011

Generic views con ForeignKey(User)

Con generic views podemos facer os accesos máis comúns á base de datos (engadir, borrar, editar, consultas...). A veces haberá que facer pequenos engadidos de código para conseguir axustes. Hoxe vamos ver cómo subir archivos ó servidor sin perder o trazo dos donos deses archivos.

models.py


Queremos aceptar un archivo que o usuario sube, e que o usuario lle dea unha descripción ó archivo. Comprobar que ese archivo sea seguro (que non nos suban un script, por exemplo) é outra tarea distinta que queda nas mans do programador.

from django import forms
from django.db import models
from django.forms import ModelForm
from django.contrib.auth.models import User
import uuid

def set_path(my_model, file_name):
'''Sets the file_path for the uploaded file'''
return "uploads/{0}".format(uuid.uuid1())

# Create your models here.
class OurModel(models.Model):
name = models.CharField(max_length=50)
user = models.ForeignKey(User, editable=False)
file_path = models.FileField(upload_to=set_path, blank=True)

def __unicode__(self):
return self.name

class OurModelForm(ModelForm):

class Meta:
model = OurModel
exclude = ("user",)


urls.py



Estando dentro da nosa aplicación, empezaremos necesitando a vista de list_detail.object_detail e a de create_update.create_object. Como imos a modificar aparte de crear o obxeto, a vista xenérica de create_object hai que desplazala a unha función de views.py (será add).

from django.conf.urls.defaults import *
from models import OurModel, OurModelForm

import views

urlpatterns = patterns('',
url(r'^(?P<object_id>\d+)/$',
"django.views.generic.list_detail.object_detail",
dict(queryset=OurModel.objects.all()),
name='ourmodel_detail'),
url(r'^add/$',
views.add,
name='ourmodel_add'),
)


views.py



Aquí creamos a función add que se chama desde urls.py. Nesta función trataremos as chamadas GET e POST, xa que o formulario ten o "action" cara sí mesmo. Si se chama vía GET, devolvemos a vista de create_object, si se chama vía POST, instanciamos o modelo cos datos que nos veñen do formulario, instanciamos un usuario (User) co usuario que está logueado e pasámoslle ambas instancias ó modelo, para que as grave.

O "truco" está en cargar o formulario e preparalo para grabar (commit=False), xa que a partir deste momento poderemos cargarlle tamén a instancia de "User". Despois da grabación, podemos redirixir o usuario cara calquer páxina, aquí mandámolo a un object_detail do recén grabado.

from django.views.generic.create_update import create_object
from django.views.generic.list_detail import object_detail
from django.contrib.auth.decorators import login_required
from django.contrib.auth.models import User

from models import OurModel, OurModelForm

@login_required
def add(request):
if request.method == "POST":
form = OurModelForm(data=request.POST,
files=request.FILES)
if form.is_valid():
our_model = form.save(commit=False)
our_model.user = User.objects.get(pk = request.user.id)
our_model.save()

return object_detail(request,
OurModel.objects.all(),
object_id=align.id)

return create_object(request,
model=OurModel,
form_class=OurModelForm,
login_required=True)


templates



Necesitamos só dous templates, /our_app/ourmodel_detail.html e /our_app/ourmodel_form.html. Con un pequeno cambio: os formularios que suben archivos teñen unha propiedade añadida

<form enctype="multipart/form-data" method="post" action="."></form>


Listo!

Resultado



Cando un usuario rexistrado accede á páxina http://ourserver.com/ourapp/add/ por primeira vez (vía GET), o urls.py lévao á función def add de views.py. Nesa función sáltase toda a parte "non POST", e simplemente saca o generic view para create_update.create_object, que presenta o formulario indicado.

Si o usuario enche o formulario correctamente (se non o fai, o generic view automáticamente volve para atrás), chámase a función add de novo, pero agora vía POST e cos datos apropiados. Agora entramos no proceso propio de grabar o modelo na base de datos cos datos apropiados.