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.