Yawd website

sep24

Managing files with django - a yawd-elfinder tutorial

I've always liked elFinder. It is a jQuery application that allows for managing files through a web page. elFinder is capable of uploading, moving, previewing and editing all kinds of files on the fly. In version 2 you can also resize, rotate and crop your images online, so it is a perfect solution for your django website's administration interface. To integrate elfinder with django we created a reusable django application, the yawd-elfinder. In this simple tutorial we will install yawd-elfinder, connect it to our models and use it in our front-end templates.

Installation

First of all we will install yawd-elfinder:

pip install yawd-elfinder

For windows users with no pip support, simply download and run the installer found here (just make sure you get the MS Windows installer) and yawd-elfinder will be installed.

Using the file manager

Let's say we have a simple Page model with a name and a content field:

in models.py
from django.db import models

class Page(models.Model):
    name = models.CharField(max_length=100)
    content = models.TextField()

    def __unicode__(self):
        return self.name

Normally, if we were to attach a file field to our Page model we would use the built-in django file field. However, to let yawd-elfinder manage our files we must use the ElfinderField, which is implemented in the yawd-elfinder app. Therefore, our model should look like this:

in models.py
from django.db import models
from elfinder.fields import ElfinderField

class Page(models.Model):
    name = models.CharField(max_length=100)
    content = models.TextField()
    anyfile = ElfinderField()

    def __unicode__(self):
        return self.name

Now the Page.anyfile property will point to an ElfinderField instance.

In order to manage our Page records we will use the django admin site, so let's register our Page model to the admin site:

in admin.py
from django.contrib import admin
from models import Page

admin.site.register(Page)

At this point make sure django.contrib.admin and elfinder are in the INSTALLED_APPS list in your settings file:

in settings.py
INSTALLED_APPS = (
    ...
    'django.contrib.admin',
    'elfinder'
    ...
)

As yawd-elfinder needs to communicate with the server to manage your files, we also need to register the elfinder urls in our url patterns:

in urls.py
from django.conf.urls import patterns, include, url
from django.conf import settings

from django.contrib import admin
admin.autodiscover()

urlpatterns = patterns('',
    url(r'^admin/', include(admin.site.urls)),
    url(r'^elfinder/', include('elfinder.urls'))
)

if settings.DEBUG:
    from django.contrib.staticfiles.urls import staticfiles_urlpatterns
    urlpatterns += staticfiles_urlpatterns()
    urlpatterns += patterns('',
        url(r'^media/(?P<path>.*)$', 'django.views.static.serve', { 'document_root': settings.MEDIA_ROOT, }),
    )

Files managed by yawd-elfinder are uploaded to your MEDIA_ROOT by default (although this can change using the ELFINDER_CONNECTOR_OPTION_SETS setting, this is beyond the scope of this guide). Therefore you must set your MEDIA_ROOT and MEDIA_URL settings as described in the django documentation.

Now run syncdb, start your web server and visit http://localhost:8000/admin/. Visit the 'Add new Page' page and you should see a screen like the one below:

The yawd-elfinder admin widget

If you upload and attach a file to the page, the administration interface should display a set of useful information about the uploaded file:

A selected file

Access the file in your templates

What we would like to do next is create a view to display our page:

in views.py
from django.views.generic import DetailView
from models import Page

class IndexView(DetailView):
    template_name = 'index.html'
    
    def get_object(self):
        return Page.objects.get(pk=1)

The above simple view will always display the contents of our first page (the one with id=1). Just make sure you have created a page through the administration interface. Now we should register the view to our urls module

in urls.py
...

urlpatterns = patterns('',
    url(r'^admin/', include(admin.site.urls)),
    url(r'^$', IndexView.as_view()),
    url(r'^elfinder/', include('elfinder.urls'))
)

...

Finally, let's create our template (in the view code we declared that the template name should be 'index.html'):

in templates/index.html
<!DOCTYPE html >
<html>
	<header>
		<title>yawd-elfinder example page</title>
	</header>
	<body>
		<div>
			<h1>{{object.name}}</h1>
			{{object.content|safe}}
			<p><a href="{{object.anyfile.url}}" target="_blank">File attachment!</a></p>
		</div>
	</body>
</html>

An ElfinderField stores its data in a special class, the ElfinderFile. As shown in the above snippet, we can retrieve the file url using the url property of the object. Therefore, with object.anyfile.url we print the file url in our template. An info property is also available. The latter will display all sorts of information about the file, like the file size, modification time, file path etc:

{{object.anyfile.info}}

Visit http://localhost:8000/ and voila, we are now using a basic setup of the yawd-elfinder file manager.

yawd-elfinder demo application

The yawd-elfinder application includes a demo project to serve as an example of its usage and demonstrate its customization capabilities. Most of the code found in this article is also available in the demo. You can also see how to quickly allow only image files or even restrict the file permissions and file types to your will. To view the demo code online please visit the github repository. For more information on how to install the demo project prease to the yawd-elfinder demo setup documentation.

Further reading

yawd-elfinder uses "volume drivers" to connect to file storage backends. At the moment, you can only store files to the local hard disk out-of-the box. However, you have full control on file permissions (read/write/lock), you can filter the allowed file types for both upload & list operations, restrict file names using patterns, disallow certain operations (e.g. copy operation or delete operation) etc. To take advantage of yawd-elfinder's more advanced capabilities, please advice the online documentation.

If you use ftp drives, amazon services, dropbox etc. for the moment you have to implement your own driver. yawd-elfinder provides a base driver interface that you should extend for your driver to communicate with the application. We are currently working on a volume driver that will support django storages so that yawd-elfinder will be able to use 3rd party storages. Please feel free to fork the project on github and send as your contributions!

Comments powered by Disqus