Package: django-user-media
as profile pictures, foto albums etc...Home-page: https://github.com/bitmazk/django-user-mediaAuthor: Martin BrochhausAuthor-email: martin.brochhaus@bitmazk.comLicense: The MIT LicenseDescription: Django User Media=================Almost all modern web apps allow their users to upload content such as audio,video or images. This raises a number of issues if that content should not bevisible to the whole world by default.If you add an ImageField to your user model, you need to come up with a goodidea on how to save those images. It is probably not a good idea to keep theoriginal filenames as they might disturb your server's file system and opendoors for hackers, who might try to brute-force against your``/media/user_profiles/`` in the hope to steal some valuable files.Since it seems inevitable to implement a function for Django's FileField's``upload_to`` attribute I thought that this might be a candidate for a reusableapp.Prerequisites-------------You need at least the following packages in your virtualenv:* Django* django-libs* easy_thumbnails* django-generic-positions* simplejsonInstallation------------To get the latest stable release from PyPi::$ pip install django-user-mediaTo get the latest commit from GitHub::$ pip install -e git://github.com/bitmazk/django-user-media.git#egg=user_mediaAdd the app to your ``INSTALLED_APPS``::INSTALLED_APPS = [...'user_media','easy_thumbnails','django_libs','generic_positions',]Hook the app into your main ``urls.py``::urlpatterns += patterns('',...url(r'^umedia/', include('user_media.urls')),)Run the migrations to create the app's database tables::$ ./manage.py migrate user_mediaUsage-----Add generic relation++++++++++++++++++++Let's assume that you have a ``UserProfile`` model and you want to add an``avatar`` field to that model.First you might want to add a [``GenericRelation``](https://docs.djangoproject.com/en/1.8/ref/contrib/contenttypes/#django.contrib.contenttypes.fields.GenericRelation) to your ``UserProfile``model::from django.contrib.contenttypes import fieldsclass UserProfile(models.Model):...user = models.ForeignKey(getattr(settings, 'AUTH_USER_MODEL', 'auth.User'),)avatar = fields.GenericRelation('user_media.UserMediaImage',)Add property++++++++++++Now you will be able to get all uploaded images that belong to a``UserProfile`` by doing this::profile = UserProfile.objects.get(pk=1)images = profile.avatar.all()It makes sense to add a convenience method to your ``UserProfile`` model::class UserProfile(models.Model):...@propertydef avatar(self):try:return self.avatar.all()[0]except IndexError:return NoneAdd link to update form+++++++++++++++++++++++In your templates you can now provide a link to the image creation view likethis (assuming that your ``UserProfile`` object is called ``object`` in thetemplate's context)::<a href="{% url "user_media_image_create" content_type="userprofile" object_id=object.pk %}">Upload your picture</a>Note that ``userprofile`` is the model name that the ``ContentType`` of your``UserProfile`` model would return. You can figure this out with ``./manage.pyshell`` for example::$ ./manage.py shellIn [1]: from django.contrib.contenttypes.models import ContentTypeIn [2]: from your_app.models import UserProfileIn [3]: ContentType.objects.get_for_model(UserProfile).modelOut [1]: u'userprofile'When visiting that link, the user will see an image upload form. You mightwant to override that template (``user_media/usermediaimage_form.html``).After uploading the image the view should redirect back to the absolute urlof your ``UserProfile``. If you want to redirect to another URL, you canprovide a ``next`` URL parameter via POST or GET::<a href="{% url "user_media_image_create" content_type="userprofile" object_id=object.pk %}?next=/foo/bar">Upload your picture</a>Display images++++++++++++++Now you should have all building blocks that you need to add links or buttonsto your templates that call the views of this application. On your``UserProfile`` detail view you could display the avatar, if available::{% if object.avatar %}<img src="{{ MEDIA_URL }}{{ object.avatar.image }}" />{% endif %}Delete and edit images++++++++++++++++++++++Or in your ``UserProfile`` update view you could display a link to upload anew image or to delete the existing image::{% if form.instance.get_avatar %}<p><img src="{{ MEDIA_URL }}{{ form.instance.avatar.image }}" /></p><a href="{% url "user_media_image_delete" pk=form.instance.avatar.pk %}">Delete picture</a>{% else %}<a href="{% url "user_media_image_create" content_type="userprofile" object_id=form.instance.pk %}">Add profile picture</a>{% endif %}The delete link in this example will render the``user_media/usermediaimage_confirm_delete.html`` template, which you mightwant to override in your project.A link for editing an existing image would look like this::<a href="{% url "user_media_image_edit" pk=form.instance.avatar.pk %}">Edit picture</a>Upload from your own model form+++++++++++++++++++++++++++++++Often you might not want to provide a dedicated form for uploading images butyou might want to have an image field right on the model form of your contentobject. In this case you can inherit from `UserMediaImageFormMixin`::from django import formsfrom user_media.forms import UserMediaImageFormMixinfrom yourapp.models import UserProfileclass UserProfileForm(UserMediaImageFormMixin, forms.ModelForm):image_label = _('Image')require_user_media_image = Falseimage_field_name = 'user_media_image'image_widget = forms.ClearableFileInput()  # optional# your form implementationThe mixin will dynamically add a `forms.ImageField` with the name`user_media_image` to your form. You can control the label of that field bysetting the `image_label` attribute on your form class. You can also make thefield mandatory by setting the `require_user_media_image` attribute to `True`.AJAX calls----------You might want to call the ``CreateImageView`` from an AJAX call, i.e. whendisplaying the form in a jQuery modal. To make life easier the view willreturn a different template when the request is an AJAX call.The names of the alternative templates are``user_media/partials/ajax_usermediaimage_form.html`` and``user_media/partials/ajax_usermediaimage_confirm_delete.html``.Make sure to add a user field to the object::user = models.ForeignKey(getattr(settings, 'AUTH_USER_MODEL', 'auth.User'),verbose_name=_('User'),)Alternatively you can add a function called ``user_can_edit``: ::def user_can_edit(self, user):"""Function, which returns True if the user is allowed edit the instance."""if user in self.users.all():return Truereturn FalseAJAX multi image upload-----------------------If you want to upload multiple images at once, only prepare the followingtemplates::user_media/partials/image_upload.htmluser_media/partials/image.htmlThen add styles and jQuery scripts. We've used blueimp's file upload, so youmake it work by adding jQuery & jQuery-UI plus the scripts in::user_media/partials/image_upload_scripts.htmlNow include the form::{% include "user_media/partials/image_upload.html" with object=request.user.get_profile maximum='5' hide_cutout='0' mode="multiple" c_type="profile" %}You can use the variable `hide_cutout="0"` to hide the link that triggers thejQuery crop functionality.You can limit the maximum upload by using the following setting::USER_MEDIA_UPLOAD_MAXIMUM = 5AJAX single image upload------------------------You can also combine single and multiple uploads. Just use the templates andadd the wanted variables::{% include "user_media/partials/image_upload.html" with object=request.user.get_profile field='logo' mode="single" show_main_thumb="True" %}Extra classes for newly loaded image------------------------------------If you are using the single image upload, your newly uploaded image willreplace the current `img`-element in your `userMediaImageUploaded`-element.Sometimes you might have special CSS classes on your images and you might wantto add those classes again to the `img` that has just been added to the DOM. Inorder to define the classes that should be added to newly loaded image, justadd the `data-img-class="myclass1 myclass2"` attribute to the element that hasthe `userMediaImageUploaded` class.jQuery image cropping---------------------You can easily add a frontend image cropping. First of all, add a new thumbnailprocessor ``user_media.processors.crop_box``::THUMBNAIL_PROCESSORS = ('user_media.processors.crop_box',...'easy_thumbnails.processors.colorspace','easy_thumbnails.processors.autocrop','easy_thumbnails.processors.scale_and_crop','easy_thumbnails.processors.filters',)Then add the cropping template and the relevant js libraries::{% include "user_media/partials/crop.html" %}<script src="{% static "django_libs/js/getcookie.js" %}"></script><script src="{% static "user_media/js/libs/jquery.Jcrop.js" %}"></script>You can modify the settings by overwriting the input fields in ``crop.html``.Check out: http://deepliquid.com/content/Jcrop.htmlNow, if a user clicks on ``Select another cutout``, the original image will bepushed into the crop area, where the user is able to select a frame. If shethen saves the cropped area, the coordinates will be saved to the``UserMediaImage`` instance.By using the new thumbnail processor it's easy to use this coordinates togenerate thumbnails::{% thumbnail image.image image.small_size box=image.box_coordinates %}Settings--------USER_MEDIA_THUMB_SIZE_SMALL+++++++++++++++++++++++++++Default: (95, 95)Size of the small auto-generated thumbnails, which are processed afterupload/cropping.USER_MEDIA_THUMB_SIZE_LARGE+++++++++++++++++++++++++++Default: (150, 150)Size of the large auto-generated thumbnails, which are processed afterupload/cropping.USER_MEDIA_UPLOAD_MAXIMUM+++++++++++++++++++++++++Default: 3Amount of images to be uploaded at a maximum.Contribute----------If you want to contribute to this project, please perform the following steps.. code-block:: bash# Fork this repository# Clone your forkmkvirtualenv -p python2.7 django-user-mediamake developgit co -b feature_branch master# Implement your feature and testsgit add . && git commitgit push -u origin feature_branch# Send us a pull request for your feature branchIn order to run the tests, simply execute ``tox``. This will install two newenvironments (for Django 1.8 and Django 1.9) and run the tests against bothenvironments.Keywords: django,common,reusable,media,files,uploadPlatform: OS Independent