On Thu, Jul 22, 2010 at 4:30 AM, Russell Keith-Magee
<russ...@keith-magee.com> wrote:
> On Sun, Jul 18, 2010 at 1:59 AM, Waldemar Kornewald
> <wkornew...@gmail.com> wrote:
>> Hi Russell,
>> so, after our chat on IRC I've finally found the time to implement a
>> real proposal including unit tests. I've attached the patch to this
>> ticket:
>> http://code.djangoproject.com/ticket/13960
>>
>> Now there is just one backend type with a single setting:
>>
>> FILE_BACKENDS = (
>>    'path.to.Backend',
>>    'path.to.Backend2',
>> )
>
> Bikeshedding, but FILE_BACKENDS is a little generic for my taste; it's
> not specifying anything about *files* per-se, it's about the upload
> and download of files.

I'm open for naming suggestions. I could rename it to FILE_TRANSFER_BACKENDS.

>> --------
>>
>> The end-user will normally use the API via ModelForm like this when 
>> uploading:
>> form = MyModelForm()
>> form.prepare_upload(request)
>
> I accept the need for this, but this seems like a bit of a wart. This
> method wouldn't be required at all if the Form took a request
> argument. This isn't an unusual requirement, either -- perhaps we
> should introduce a RequestForm/RequestModelForm that formalizes the
> availability of the request object during form processing.

Maybe. Then RequestForm could be used for hinting (instead of
Model/FileField). The constructor would take a target_url parameter
and take care of adding hidden input fields if they're required for
the upload. However, I also added this dependency because I wanted to
provide some useful hint for download_url() and serve().

>> Backends
>>
>> Every backend derives from BaseFileBackend. Every backend instance has
>> these members:
>> * self.model: the model that own the FileFields to upload to or download from
>
> Except that there's no guarantee that a Form will be backed by a
> model. You can upload a file without a model being involved.

I was thinking in terms of file uploads for storage on the server. In
that case the file file upload mechanism might only work with one
specific file storage backend (which is defined on FileField). We
could try to make it independent of the model, but then the question
is: Should we make file downloads independent of the Model/Field, too?
How do we handle file downloads without using a model/field as the
hint?

Tag names could have name clashes and not all developers will
appreciate that they suddenly have to give every form and file
download a unique tag. I'm not sure if tag names are the best
solution, but I don't have any better alternative, either. Is this
really the way it should be used?

Maybe we can at least auto-generate tag names?

# FileField needs a tag to select the storage backend
class MyModel(models.Model):
    file = models.FileField(tag='myapp')

# Should the default tag be generated from model and field?
class MyModel(models.Model):
    file = models.FileField() # tag defaults to
'myapp.models.MyModel.file' or something like that

# Forms need a tag argument
# (again, maybe the default tag could be auto-generated, e.g.
'myapp.forms.MyRequestForm'?)
MyRequestForm(request, tag='myapp')

# Files get the default tag from their FileField
# or you have to manually set
# file.tag = '...'
# (this would always be necessary for request.FILES)
file.download_url()
file.serve(request)

> Once such a name is available, you may also find that the cascading
> behavior isn't actually required. Cascading is necessary in the case
> of database routers because you may need to consider several factors
> before deciding which database needs to be used; however, in the case
> of file uploads, the uploading behavior isn't really dynamic -- form X
> will always be backed by upload mechanism Y. All you really need is a
> way of performing that mapping.

The request (and request.user) is a dynamic component in the upload
process, so the cascading could still be needed. I'm not sure if we
should remove the request from the backend API. At least, I could
imagine that file downloads need the request to run some permission
checks against the user.

> There are three pieces to this puzzle.
>  a) The mechanics for how to do a file transfer to S3, etc
>  b) Configuring a specific instance of an S3 transfer backend to point
> at a particular path
>  c) Configuring which backend should be used for which form.
>
> At the moment, it appears that your convolving all three roles into
> one backend class. To my mind, (b) should be an instantiation of (a),
> and (c) is a separate issue for determining which (b) instance is
> required at any given time. That is, the routing behavior and the file
> upload logic shouldn't be part of the same class as the backend
> itself. (By analogy, the database routers determine which database
> will be used, but contain no logic to actually write to a database).

I agree that these things should be separated, so you'd have one S3
backend which takes care of file transfers, but does no routing and a
separate backend would handle only the routing, but not file
transfers. I just don't think we need to implement different APIs for
these concepts because the APIs would be basically identical, anyway
(both getting the same parameters and providing the same functions).

Bye,
Waldemar Kornewald

-- 
You received this message because you are subscribed to the Google Groups 
"Django developers" group.
To post to this group, send email to django-develop...@googlegroups.com.
To unsubscribe from this group, send email to 
django-developers+unsubscr...@googlegroups.com.
For more options, visit this group at 
http://groups.google.com/group/django-developers?hl=en.

Reply via email to