""" Django Jcrop form Author: Markus Thielen, mt@thiguten.de = Description = Implements a Django form that integrates image uploading plus cropping using the awesome Jcrop plugin (http://deepliquid.com/content/Jcrop.html). It does not create or use any models, so to use it, simply copy it to your project tree and import it as appropriate. = License = MIT = Limitations = Many, probably ;-) It does basically work but lacks proper error handling. If you upload something that is not an image, no error is dispayed. I hope I find the time to fix this. If you have a hint, I'd be grateful if you dropped me a note. = Usage = In your views.py, import JcropForm. The view function that displays the form has three parts (or control flows): * if request is POSTed but contains no uploaded files, crop coordinates were submitted. Use JcropForm's crop/resize/save methods to apply. * if request was posted with file data, the user just uploaded a new image. Use JcropForm's static method prepare_uploaded_img to scale the image to a reasonable size (that does not break your layout) and save it * for normal GET requests just display the form with the current image. Example view function: @login_required # the view func expects a logged on user def img_edit_view(request): # get the profile (i.e. the model containing the image to edit); # In this example, the model in question is the user profile model, # so we can use Django's get_profile() method. profile = request.user.get_profile() # define a fixed aspect ratio for the user image aspect = 105.0 / 75.0 # the final size of the user image final_size = (105, 75) if request.method == "POST" and len(request.FILES) == 0: # user submitted form with crop coordinates form = JcropForm(request.POST) if form.is_valid(): # apply cropping form.crop() form.resize(final_size) form.save() # redirect to profile display page return HttpResponseRedirect("/myprofile/") elif request.method == "POST" and len(request.FILES): # user uploaded a new image; save it and make sure it is not too large # for our layout img_fn = JcropForm.prepare_uploaded_img(request.FILES, image_upload_to, profile, (370, 500)) if img_fn: # store new image in the member instance profile.avatar = img_fn # 'avatar' is an ImageField profile.save() # redisplay the form with the new image; this is the same as for # GET requests -> fall through to GET elif request.method != "GET": # only POST and GET, please return HttpResponse(status=400) # for GET requests, just display the form with current image form = JcropForm(initial = { "imagefile": profile.avatar }, jcrop_options = { "aspectRatio":aspect, "setSelect": "[100, 100, 50, 50]", } ) return render_to_response("profile/img_edit.html", { "form": form, }, RequestContext(request)) The template is the same as for normal Django forms, nothing special there. This code is somehow inspired by https://github.com/azizmb/django-ip-form, although the original code did not work for me. """ from django import forms from django.conf import settings from django.utils.safestring import mark_safe from django.utils.datastructures import MultiValueDictKeyError import Image as pil UPLOAD_IMG_ID="new-img-file" class JcropWidget(forms.Widget): class Media: # form media, i.e. CSS and JavaScript needed for Jcrop. # You'll have to adopt these to your project's paths. css = { 'all': (settings.MEDIA_URL + "css/jquery.Jcrop.css",) } js = ( settings.MEDIA_URL + "js/lib/jquery.Jcrop.min.js", ) # fixed Jcrop options; to pass options to Jcrop, use the jcrop_options # argument passed to the JcropForm constructor. See example above. jcrop_options = { "onSelect": "storeCoords", "onChange": "storeCoords", } # HTML template for the widget. # # The widget is constructed from the following parts: # # * HTML - the actual image used for displaying and cropping # * HTML