Jul 18, 2011

Django: Beautiful multiple files Upload Plugin using jQuery UI.

After successful developing python back-end for Sebastian Tschan jQuey Plugin  I've decided to make a reusable app for that purpose. So:

This is a plugin, made using multiupload form from Sebastian Tschan.
It uses jQuey UI and jQuery instead of Flash uploader.
On Django side it uses sorl-thumbnails and PIL.
You can use it in your applications with simple inclusion tag

jQuery Features it has:
  • Multiple file upload:
    Allows to select multiple files at once and upload them simultaneously.
  • Drag & Drop support:
    Allows to upload files by dragging them from your desktop or filemanager and dropping them on your browser window.
  • Upload progress bar:
    Shows a progress bar indicating the upload progress for individual files and for all uploads combined.
  • Cancelable uploads:
    Individual file uploads can be canceled to stop the upload progress.
  • Resumable uploads:
    Aborted uploads can be resumed with browsers supporting the Blob API.
  • Chunked uploads:
    Large files can be uploaded in smaller chunks with browsers supporting the Blob API.
  • Preview images:
    A preview of image files can be displayed before uploading with browsers supporting the required HTML5 APIs.
  • No browser plugins (e.g. Adobe Flash) required:
    The implementation is based on open standards like HTML5 and JavaScript and requires no additional browser plugins.
  • Graceful fallback for legacy browsers:
    Uploads files via XMLHttpRequests if supported and uses iframes as fallback for legacy browsers.
  • Standard HTML file upload form:
    Shows a standard HTML file upload form if JavaScript is disabled.
  • Cross-site file uploads:
    Supports uploading files to a different domain with Cross-site XMLHttpRequests.
  • Multiple plugin instances:
    Allows to use multiple plugin instances on the same webpage.
  • Customizable and extensible:
    Provides an API to set individual options and define callBack methods for various upload events.
  • Multipart and file contents stream uploads:
    Files can be uploaded as standard "multipart/form-data" or file contents stream (HTTP PUT file upload).
  • Compatible with any server-side application platform:
    Works with Google App Engine (Python, Java), Ruby on Rails, PHP and any other platform that supports HTTP file uploads.
 Python Features:
  • Uses own model for temporary storing files:
    Uploaded files Model can be used anywhere in your code or transferred to another model of your choice.
  • Can be added using 2 simple templatetags:
    {% load multiuploader %} and {% multiupform %} in a form place.
  • Opensource!


Adding this AJAX form to your web site is as simple, as adding this 2 tags to your template:

    {% load multiuploader %}
    {% multiupform %}

It has it's own model for storing images there.
It has some bugs a bit but is quite usable. Feel free to use it in your projects.

Demo is available on Sebastian's website: http://aquantum-demo.appspot.com/file-upload
You can try it there but without python back-end.

I'm using it on my Photoblog: http://garmon.elutsk.net/

Finally you can download/fork it and view installation instructions on my GitHub repository dedicated for it: https://github.com/garmoncheg/django_multiuploader

UPD: I've done a demo app with usage of this plugin. Maybe it will be usefull to figure out some undescribed usage moments or so. https://github.com/garmoncheg/django_multiuploader_example_usage

Jul 12, 2011

Django: Creating multi upload form without using Flash

Hi there! Today I want to tell you about my experience of adding Multiple files upload form to my Django project Photoblog. I searched google for lots of plugins, but found only Flash usage examples. I dislike Flash technology, as for my personal usage, and want to build some more quickly working UI. Personally I have flash blocker installed on my browser. So that's main ideas pf my jQuery plugin selection. I found IMHO the best for my case plugin by Sebastian Tschan. It had only one problem - No available Django examples. Let's try to fill the gap here... So my experience on befriending Sebastian Tschan's jQuery File Upload Plugin with Django is the topic of this article. Let's finally get started. :)

Sebastian has built an important plugin IMHO. I want to thank him for his noble work of helping people with their tasks. It uses only jQuery UI and no flash, making it work more programmers way... So enough with the lyrics.

Let's try to adapt his example to a django Project. I used new one, built with Eclipse using Django 1.3. So fell free to create yours and Download Sebastian's plugin. After that we will get existing project using PHP as main gear. Let's try to adapt it.

Main problems I met creating it:
    - jQuery UI uses similar templates language with Django.
    Problem solved by changing Django code to generate '{{' scopes instead variables '{{ open_tv }}' and '}}' instead '{{ close_tv }}' accordingly. You can watch it in template example of this demo project.
    - write view to get files from AJAX form and return proper JSON in response. You can examine mine in app multiuploader.
    - write view to delete uploaded photo. Mine is multiuploader_delete.
    - generate thumbnail for showing uploaded image. I used sorl-thumbnails that uses PIL.
    - generate JSON response to form like this:

{"name":"picture1.jpg","size":902604,"url":"//example.org/files/picture1.jpg","thumbnail_url":"//example.org/thumbnails/picture1.jpg","delete_url":"//example.org/dlete/1/","delete_type":"POST"},
{"name":"picture2.jpg","size":841946,"url":"//example.org/files/picture2.jpg","thumbnail_url":"//example.org/thumbnails/picture2.jpg","delete_url":"/example.org/delete/2/","delete_type":"POST"}


Let's get straight to business. So imagine this simple model. It has only image and title (used image's file name for title):

#models.py
from django.db import models

class Image(models.Model):
    title = models.CharField(max_length=60, blank=True, null=True)
    image = models.FileField(upload_to="images/")
    
    def __unicode__(self):
        return self.image.name

Now let's write urls as we need for main images view, multiuploader form and file deletion like so:
#urls.py
from django.conf.urls.defaults import *

from multiuploader.views import multiuploader_delete

urlpatterns = patterns('',
    (r'^delete/(\d+)/$', multiuploader_delete),
    url(r'^$', 'django_multiuploader_demo.multiuploader.views.image_view', name='main'),
    url(r'^multi/$', 'django_multiuploader_demo.multiuploader.views.multiuploader', name='multi'),
    
)
Main view is quite simple. It's just for handy demo that photos exist after upload. It will look like so:

#views.py
def image_view(request):
    items = Image.objects.all()
    return render_to_response('images.html', {'items':items})

It will pass our model directly to template. It will render our model like so:

#multiuploader_main.html
{% load thumbnail %}
<h1><a href="{% url multi %}">Multiuploader</a></h1>
<br />
<h2>Images:</h2>
<hr>
<div class="photos">
{% for item in items %}
{% thumbnail item "80x80" crop="10px 10px" as im %}
    <img src="{{ im.url }}" width="{{ im.width }}" height="{{ im.height }}">
{% endthumbnail %}
{% endfor %}
</div>
<hr>

Final result is simple images model:
Now that we have application to upload photos to let's proceed.
Let's create a a main view that will return our multiuploader template in cese of GET and receive POST requests with photos. It might look like so:

#views.py
def multiuploader(request):
    if request.method == 'POST':
        log.info('received POST to main multiuploader view')
        if request.FILES == None:
            return HttpResponseBadRequest('Must have files attached!')

        #getting file data for farther manipulations
        file = request.FILES[u'files[]']
        wrapped_file = UploadedFile(file)
        filename = wrapped_file.name
        file_size = wrapped_file.file.size
        log.info ('Got file: "'+str(filename)+'"')

        #writing file manually into model
        #because we don't need form of any type.
        image = Image()
        image.title=str(filename)
        image.image=file
        image.save()
        log.info('File saving done')

        #getting url for photo deletion
        file_delete_url = '/delete/'
        
        #getting file url here
        file_url = '/'

        #getting thumbnail url using sorl-thumbnail
        im = get_thumbnail(image, "80x80", quality=50)
        thumb_url = im.url

        #generating json response array
        result = []
        result.append({"name":filename, 
                       "size":file_size, 
                       "url":file_url, 
                       "thumbnail_url":thumb_url,
                       "delete_url":file_delete_url+str(image.pk)+'/', 
                       "delete_type":"POST",})
        response_data = simplejson.dumps(result)
        return HttpResponse(response_data, mimetype='application/json')
    else: #GET
        return render_to_response('multiuploader_main.html', 
                                  {'static_url':settings.MEDIA_URL,
                                   'open_tv':u'{{',
                                   'close_tv':u'}}'}, 
                                  )


Now let's add the view that will delete photos for us. It might look like so:

#views.py
def multiuploader_delete(request, pk):
    if request.method == 'POST':
        image = get_object_or_404(Image, pk=pk)
        image.delete()
        return HttpResponse(str(pk))
    else:
        return HttpResponseBadRequest('Only POST accepted')

Finally main Form would look similar to this:


I will not provide main template of uploader, because it's quite big. You can fork/download it from my django_multiuploader_demo at github.

Feel free to use this demo anyhow in your project, but please drop me a comment here if you find it useful. 

Ideas, Suggestions, Critics? Welcome to comments...

Jul 11, 2011

Django: How to add Google +1 button to your website.

What is Google +1 button?

It's new Google social button. It's much similar to Facebook "Like" button. While available during one month it earned popularity that could compete with Facebook's social button. Corporation of Good knows what to do, so you probably want to have one on your website inline with Facebook's Like...

Add Google +1 button to your site:

- Open http://www.google.com/webmasters/+1/button/index.html and generate own button for your website.

Google proposes HTML code like this:

<html>
  <head>
    <title>+1 demo: Basic page</title>
    <link rel="canonical" href="http://www.example.com" />
    <script type="text/javascript" src="https://apis.google.com/js/plusone.js">
    </script>
  </head>
  <body>
    <g:plusone></g:plusone>
  </body>
</html>

It's quite simple, as you can see. And that's much pretty it. Oh no wait...

- Add some variable to your template like "google_target_url" like this:

#pass variable to template with google +1 target url
return render_to_response("template.html", 
                         {"google_target_url":google_target_url,})

Finally you can add property "href" (similar to common a href=" " pattern) to target +1 action to custom url. In general you can now generate page with multiple +1 buttons on it. For e.g.: one button under one blogpost or image...


<g:plusone href="http://www.example.com/custom_page1/" size="standard" count="false"></g:plusone>

Note some more useful parameters like size and displaying counter. You can read about all options on it's FAQ. It's quite good to quickly build one to yourself in any case.

Comments/suggestions? Comment please...



Jul 7, 2011

Django: Setting up Django virtual environment via python Virtualenv with Eclipse. Quick guide.

Prologue
Hi! Let's talk about Django ways to code. First you have to have environment installed for work with Django. Today I'll try to show you my way of using virtual environment (python virtualenv).
It's ok to handle package dependencies in Django apps by simply manually putting libraries, are in need for your project, into project PYTHONPATH. It's an easy way to do it. BUT what if you would like to make another project with this environment (e.g. the same modules, plugins or app's set)... You will have to add all those modules to your new project. Another issue that if would like to code for existing project, like for e.g. open someone's work and add some modules to it. Virtualenv is a newly fashioned package which aims to combine the best features of a workingenv with a virtual Python install. Also you can say that it is a tool to create isolated in a sandbox Python environments. So... This article is about how to set up, run and connect to Eclipse new django project in a few minutes, using virtualenv and Django.


Install virtualenv

Installing virtualenv is easy on a Linux or Mac system, but the instructions that follow are MAC (OS X 10.7) specific. First you’ll need setuptools. It's an extremly handy programmers script to install new python modules in 'Plug'n'Pray' way. You need to get setuptools installed from http://pypi.python.org/ for e.g.:

- Download the appropriate egg for your version of Python (e.g. setuptools-0.6c9-py2.7.egg). Do NOT rename it.
- Run it as if it were a shell script, e.g.:


sh setuptools-0.6c9-py2.7.egg 
Setuptools will install itself using the matching version of Python (e.g. python2.7), and will place the easy_install executable in the default location for installing Python scripts (as determined by the standard distutils configuration files, or by the Python installation).

Now you have a nice way to install python packages. Let's install virtualenv. Now you only have to type:


sudo easy_install virtualenv
Sudo commend is because you need root to make some system changes. Now you can jut do virtualenv ENVNAME.

Create new virtualenv

Now that you have all system apps installed. Let's create you a new virtualenv. Pypi.python.org has a good extended (but still brief) manual on commends and basic configurations. Change directory to place in where you keep your projects. (For me it's cd /Users/username/developer/tutorial/django_projects/). Now you can run:


virtualenv --no-site-packages latest_django_venv
In this case I’ve chosen latest_django_venv as my virtual environment's name. The —no-site-packages command tells virtualenv not to symlink the global site packages into my local environment, just take the Python basic libraries set. This is important, because it helps us avoid the dependency difficulties mentioned above. As a result you'll probably see something like this:


New python executable in latest_django_venv/bin/python
Installing setuptools............done.

Install Django

Virtualenv creates its own Python and easy_install binaries, which means you can install/run things in your environment. Let’s install Django using your newly created environment:


./latest_django_venv/bin/easy_install django
You will probably see a new Django installation to your dir like so for e.g.:


Searching for django
Reading http://pypi.python.org/simple/django/
Reading http://www.djangoproject.com/
Best match: Django 1.3
Downloading http://media.djangoproject.com/releases/1.3/Django-1.3.tar.gz
Processing Django-1.3.tar.gz
Running Django-1.3/setup.py -q bdist_egg --dist-dir /var/folders/Lc/LczB6LACE-ChJ8TIuHk4Jk+++TI/-Tmp-/easy_install-RLkEvA/Django-1.3/egg-dist-tmp-S2BxFN
zip_safe flag not set; analyzing archive contents...
django.conf.__init__: module references __file__
...
django.utils.unittest.loader: module references __file__
django.views.i18n: module references __file__
Adding Django 1.3 to easy-install.pth file
Installing django-admin.py script to /Users/username/developer/tutorial/django_projects/latest_django_venv/bin

Installed /Users/username/developer/tutorial/django_projects/latest_django_venv/lib/python2.7/site-packages/Django-1.3-py2.7.egg
Processing dependencies for django
Finished processing dependencies for django
Now finally you have everything set up with Django. You may also setup any other your packages at this stage like MySQL or iPython. I will not cover those things and it's up to you... It's also good idea to add your virtualenv directory to .gitignore file, cause you probably don't want your virtualenv uploaded to upstream.

Run Django

Now that you have everything setup you can create new Django app. You'll probably skip this step in case you setting up environment for the existing project.

Note that you must use your virtualenv binaries instead of system one's. It's a bit tricky to remember at the exact needed moment sometimes. Let's type:


./latest_django_venv/bin/django-admin.py startproject newapp

Here newapp is your project name.  Note that we used django-admin script from newly created virtualenv binaries.

Now we came to almost obvious step to run Django server. Let's enter newly created app dir  and run it like so:


cd newapp
../latest_django_venv/bin/python manage.py runserver 127.0.0.1:8000
You will probably see server running with no errors.
Let's check the browser pointed at http://127.0.0.1:8000/. Ta-Da!

Now you may add it to your Eclipse project. 

Connect to Eclipse

Now that you have everything working let's try to add some GUI to this method. I use Eclipse with PyDev installed like was described in my previous article. So I just add add myself a new interpreter to it. If you need to setup eclipse from scratch try to read this article. Maybe it will help you to workout something... Nevertheless Let's add a new Python Interpreter to our Preferences > PyDev > Interpreter - Python settings. You must hit New... and specify a path to your newly made virtualenv. You will see something like so:

Now hit ok and select what have to be indexed. Note that you have to hit Select All at this step. It will get "lib" folder from root python install. It's OK, because virtualenv does not copy lib folder to new environment by default. You will probably see something like so:


And finally we received new interpreter in our Ecplipse environment:

Now upon new project creation (or existing project) you can select this interpreter to use in it. You will use Project run/debug configuration and Interpreter tab there to select your new virtualenv interpreter:

Hope this article will help someone to setup Eclipse to work with Virtualenv and Django.  And now, as always: Thoughts/suggestions? Please drop me a comment here...

Jul 4, 2011

How to disable/enable an element with jQuery or Javascript

jQuery

Sometimes you need to disable/enable the form element like input or textarea. Jquery helps you to easily make this with setting disabled attribute to "disabled".
For e.g.:
//To disable 
$('.someElement').attr('disabled', 'disabled');


To enable disabled element you need to remove "disabled" attribute from this element or empty it's string. For e.g:
//To enable 
$('.someElement').removeAttr('disabled');
// OR you can set attr to "" 
$('.someElement').attr('disabled', '');


Javascript

My case was a bit different. I had to disable simple control element used without a form.
<a class="rotator" href="" onclick="return rotate(this, parameter, url)" >

I made a javascript like this:

/** script */
var disabled = false;
function rotate(button, parameter, url)
{
    if (disabled)
        return false;
    disabled = true;
    /** some before post operations like making element visually 
        disabled and adding some waiting animation to it */
    $.post(url, {
        parameter: parameter,
    }, function(data) {
        /** some after post operations for e.g. 
            changing alpha of elements back or disabling 
            waiting scroller  */
        disabled = false;
        return false;
    });
    return false;
}

So in general you have a boolean variable set to "false". Upon script first call it is set to "true" while script works up to it's completion. After completion boolean variable is set back again to "false". During script operations it will return "false", disallowing to run it again and making my <a> control disabled.


Comments/Suggestions? Please drop me a comment about your way if you have better maybe...

Django: upgrading django from 1.1 to 1.2.5 and CSRF protection modifications

Greetings!
Yesterday I completed a quick upgrade from django version 1.1 to oldest supported 1.2.5. I had a lot of background for doing so:
- Fist my hosting has django 1.2.5 already installed.
- Second I had some thoughts on using old stuff. It's better to evolve in Djngo version too :)
- Third and the main: Newly found on Google social authentication plugin was the final dot in my decision...

So I'll try to provide My experiences on migrating (updating) my project's Django from version 1.1 (developed on it) to oldest now supported 1.2.5.

Let's get started.

1. Read the release 1.2 docs. 
I needed a quick solution. In general I had some issues with site giving me errors with {csrf_token} not present in a form's POST request.

To handle this and IMHO main issue upon upgrading you have to handle Cross Site Request Forgery protection backwards incompatible upgrade.  You can read official django docs about new CSRF protection and/or use this quick manual.

2. Add CSRF Middlewares to your settings.MIDDLEWARE_CLASSES
You need to add 'django.middleware.csrf.CsrfViewMiddleware', and 'django.middleware.csrf.CsrfResponseMiddleware', to your MIDDLEWARE_CLASSES and change olde one beginning with 'django.contrib.csrf.middleware. ...' if there persisted any.

3. Fix existing forms  
Now you need to add {{ csrf_token }} inside all forms posted by HTML methods. Note that forms must be submitted not by Javascript of some kind! or if like it was in my case jQuery plugin to override POST method takes all form data and simply submits it. So Javascript in my case wasn't a problem.
so for e.g. you new form header might look like:

<form action="" method="post">{% csrf_token %}


4. Finally polish errors appeared
Now that is don you need to add @csrf_exempt view decorator to views which take POST requests without a form or use anyhow POST request in order to work properly.
So your view decorated may look like:

from django.views.decorators.csrf import csrf_exempt

@csrf_exempt
def my_view(request):
    return HttpResponse('Hello world')

I know this is not a right way to do it but the quickest to fix issues IMHO.


Thoughts/suggestions? please drop me a comment below...

Jul 3, 2011

Briss Trims PDFs so They Fit Better, Are Easier to Read on Your Kindle



Windows/Mac/Linux: Virtually every current ereader offers native support for the PDF format, but no PDF was designed for your ereader's 5-7" screen. Briss, a cross-platform open-source tool, gives you several ways to trim PDFs to look better on your ereader.

Briss's user-interface is spare but simple. After loading a PDF file, Briss scans the document to identify and group pages with the same approximate structure into different batches. With books, it's usually even- and odd-numbered pages, because of the way the margins line up. The genius part is that you can trim every page in a batch to exactly the same size and shape, all at once. Start at a corner and drag a blue rectangle over the area you want to keep, then repeat for each batch (see the screenshots above and below).

Briss is particularly good for three things: trimming enough negative space around the text to make the document readable on a small screen, converting two-page "spread" landscape documents to single-page, portrait-oriented files, and knocking off marginal text like page numbers and chapter titles so you can use a free tool like Calibre to convert PDFs into EPUB, MOBI, or any other ereader format without the extra text popping up in the middle of a paragraph and making a mess.

Briss is a free, open source download (with a clever name) for Windows, Mac, and Linux. Do you have another tool you like to use to trim and edit PDFs? Let us know in the comments.

Briss [SourceForge]

Original Post by Lifehacker