Re: removable file field and other features

2011-01-02 Thread Daniel Carvalho
On 12/20/2010 12:55 AM, Daniel Carvalho wrote:
> Everybody knows the default django FileField doesn't allow to remove an
> existing file...
> 
> This is a good replacement. Just use RemovableFileField instead of
> FileField in your models:
> http://djangosnippets.org/snippets/636/
> 
> 
> I want to implement on it another feature- When there is a file being
> uploaded, but the form fails validation for other reason, I want to keep
> the file in the server, so no need to upload the file again. The next
> time the form is submit I would take the file and save it in the model.
> 
> 
> BUT this is not possible because there is (apparently) no way to acess
> the request object inside RemovableFileField nor from the widget...
> 
> SO I think I have to implement this in the ModelForm, or in the
> ModelAdmin, which is a more ugly solution.
> (any ideas???)
> 
> 


If anyone wants to use it, I implemented this solution.

Just use FilesModelAdmin for your models that have file or image fields.

1. A checkbox will be displayed, to remove the current value, if the
field supports blank values.
2. The uploaded files are stored in session variables for later use, in
case the form fails validation you don't need to upload then again.
3. It works for inline models also.

Problem:
if the user is editing two forms at the same time in the same session,
the uploaded files will be mixed...




# coding: utf-8
from django.contrib import admin
from django import forms
from django.utils.safestring import mark_safe

from django.utils.translation import ugettext, ugettext_lazy as _

import django.core.files
import re
import tempfile, shutil

from django.db import models

# if we have a field called "imagem", the associated checkbox for
deleting the file will be "imagem"  + REMOVE_SUFFIX,  "imagem__remove"
REMOVE_SUFFIX = "__remove"

# The session variable name we will use to store the uploaded files
SESSION_NAME = "save_uploaded_files"

import threading

# remember the request value
# so it can be accessed from any place in the thread
def set_current_request(request):
   global local
   local = threading.local()
   local.current_request = request

def get_current_request():
   global local
   return local.current_request


class FileWidget(forms.FileInput):
   # if this file accepts blanks or not
   # This will define if we put a checkbox for removing the file
   blank = False

   def render(self, name, value, attrs=None):

  output = []
  if value:
 # file has a current value

 if hasattr(value, "url"):
# the file value is the value stored in the model
output.append('%s %s %s ' % \
 (ugettext('Currently:'), value.url, value,
ugettext('Change:')))

 else:
# the file value is the file uploaded in the previous
request but not saved yet, because the form validation failed:
output.append('%s %s %s ' % \
 (ugettext('Not saved yet:'), value,
ugettext('Change:')))

 # If it has a current value, and the field accepts blanks,
 # we place a checkbox for removing it
 if self.blank:
request = get_current_request()

name_checkbox = name + REMOVE_SUFFIX

# This is important to remember the checkbox state,
# when the form is submited but fails validation, and is
displayed again
if request and name_checkbox in request.POST.keys():
   checked = 'checked="on"'
else:
   checked = ''

output.append(' %s ' % (name_checkbox, name, checked,
name, ugettext('Remove')))

  output.append(super(FileWidget, self).render(name, value, attrs))

  return mark_safe(u''.join(output))

# The same, but accepts blanks
class FileWidgetBlank(FileWidget):
   blank = True


# This ModelAdmin offers this funtionalities:
# For each file or image field, keeps uploaded files in the server even
if the form fails validation, so they dont need to be uploaded again.
When the form is saved, the uploaded files are also saved to the model.
# Put a checkbox for removing the file, it it accepts blanks.
# This also works for inline models, which have to be FilesStackedInline
class FilesModelAdmin(admin.ModelAdmin):

   def formfield_for_dbfield(self, db_field, **kwargs):
  # is it file or image?
  if type(db_field) in [ models.ImageField, models.FileField]:
 if db_field.blank:
# accept blank?
kwargs['widget'] = FileWidgetBlank
 else:
kwargs['widget'] = FileWidget
  return super(FilesModelAdmin,
self).formfield_for_dbfield(db_field,**kwargs)

   # This function is called before add_view and change_view
   # It saves the uploaded files, and at the same time restores previous
uploaded files.
   def manage_uploads(self, request):

  # this is for the request to be accessible from FileWidget

  # I could have implemented get_form doing this:
  

removable file field and other features

2010-12-19 Thread Daniel Carvalho
Everybody knows the default django FileField doesn't allow to remove an
existing file...

This is a good replacement. Just use RemovableFileField instead of
FileField in your models:
http://djangosnippets.org/snippets/636/


I want to implement on it another feature- When there is a file being
uploaded, but the form fails validation for other reason, I want to keep
the file in the server, so no need to upload the file again. The next
time the form is submit I would take the file and save it in the model.


BUT this is not possible because there is (apparently) no way to acess
the request object inside RemovableFileField nor from the widget...

SO I think I have to implement this in the ModelForm, or in the
ModelAdmin, which is a more ugly solution.
(any ideas???)




signature.asc
Description: OpenPGP digital signature