Custom Search

Friday, April 23, 2010

Dynamic file upload paths in Django

Dynamic file upload paths in Django

============================== Example 1 (Not using ModelForm)

Not using CustomImageField, it is old technique

Pass a callable in upload_to
-------------------------------------
It is now possible for the upload_to parameter of the FileField or ImageField to be a callable, instead of a string. The callable is passed the current model instance and uploaded file name and must return a path. That sounds ideal.

Here’s an example:


------------------------ in models.py

import os
from django.db import models

def get_image_path(instance, filename):
return os.path.join('photos', instance.id, filename)

class Photo(models.Model):
image = models.ImageField(upload_to=get_image_path)

------------------------OR in models.py

import os
from django.db import models

class Photo(models.Model):
def get_image_path(self, filename):
return os.path.join('photos', self.id, filename)

image = models.ImageField(upload_to=get_image_path)

--------------------------

get_image_path is the callable (in this case a function). It simply gets the id from the instance of Photo and uses that in the upload path. Images will be uploaded to paths like:

photos/1/kitty.jpg

You can use whatever fields are in the instance (slugs, etc), or fields in related models. For example, if Photo models are associated with an Album model, the upload path for a Photo could include the Album slug.

Note that if you are using the id, you need to make sure the model instance was saved before you upload the file. Otherwise, the id hasn’t been set at that point and can’t be used.

For reference, here’s what the main part of the view might look like:

------------------------ in views.py

if request.method == 'POST':
form = PhotoForm(request.POST, request.FILES)
if form.is_valid():
photo = Photo.objects.create()
image_file = request.FILES['image']
photo.image.save(image_file.name, image_file)



This is much simpler than the hacks used in CustomImageField and provides a nice flexible way to specify file or image upload paths per-model instance.

Note: If you are using ModelForm, when you call form.save() it will save the file – no need to do it yourself as in the example above.
-----

============================== Example 2 (Using ModelForm)

------------------------ in models.py

import os
from django.db import models

def get_image_path(instance, filename):
return os.path.join('photos', instance.id, filename)

class Photo(models.Model):
image = models.ImageField(upload_to=get_image_path)

------------------------OR in models.py

import os
from django.db import models

class Photo(models.Model):
def get_image_path(self, filename):
return os.path.join('photos', self.id, filename)

image = models.ImageField(upload_to=get_image_path)

----------------------- in forms.py

class MockupForm(ModelForm):
class Meta:
model = Photo

----------------------- in views.py

if request.method == 'POST':
form = PhotoForm(request.POST, request.FILES)
if form.is_valid():
form.save()

Note: You are using ModelForm,So when you call form.save() it will save the file automatically.

==============================

No comments:

Post a Comment