Django Admin show Image immediately after upload - django

maybe this issue is answered elsewhere, but I have no luck of finding it.
Here is my issue:
I have a Django admin site that has an ImageField to upload image look like this
In order to show the uploaded image, I will have to click on Save/ Save and add another/ Save and continue editing.
What I really want is show preview of the picture immediately after I upload it.
Is there anyway to trigger it via ImageField override or somehow?
Any suggestion would be appreciated

You can't do that because you haven't actually uploaded the image yet. When you "choose file" you've basically just told the browser which file you want to upload, but it doesn't get uploaded until you submit the form.

I am using sorl.thumbnail, but you can easily adapt it into django.
Below is Django model class
Class ImageModel(admin.Models):
...
myfield = models.ImageField(_("Image"), upload_to='project/%Y', null=True, blank=True)
...
#property
def image_tag(self):
im = get_thumbnail(self.myfield.file, 'x300', crop='center', quality=99)
return mark_safe('<img src="%s" width="%s" height="%s" />' % (im.url, im.width, im.height))

Related

Django ImageField Creating New Folder by ID on upload?

I'm Currently developing a app with a ManyToMany ImageField Relantionship . I want to have the ImageField save all images to a specific folder based on the ID of the Relantionship.
I want to have something like this.
class PostImages(models.Model):
image = models.ImageField(upload_to='Post_Images/post/' + post.id)
class Post(models.Model):
images = models.ManyToManyField(PostImages)
How do I access the post.id to do this ? I mostly want to do this for organization purposes right now cause its on my local machine but also see no reason to change it when I deploy.
E.g. based on FileField^ but the same you can use for ImageField:
def get_file_path(instance, filename):
return instance.created.strftime("folder/%Y/%m/%d/") + instance.post.id
bfile = models.FileField(upload_to=get_file_path, null=True)

Django ClearableFileInput - how to detect whether to delete the file

I'm using Django Crispy Forms for my form with an option to upload an image (ImageField in my Model)
The forms renders as I'd expect, with the checkbox to clear an existing file. However when processing the form submission the 'image-clear' checkbox always gives me a 'None' value.
image_clear = form.cleaned_data.get("image-clear")
print image_clear
In the HTML of the page I notice that the input checkbox doesn't have a value attribute, see:
<input id="image-clear_id" type="checkbox" name="image-clear">
So I wondered if this was the issue, but when I look at the rendering in the Django admin site, the corresponding HTML input field doesn't have a value either - yet it still identifies that the image should be removed.
I should note that if I upload a new image, then this works, it's only the case where I'm removing/clearing the image (and it works in Django admin pages, so assume that means my model definition is ok to allow no image to be attached to the model)
So... in my form processing, how do I detect whether or not the image should be removed or not?
I'm sure I'm missing something simple here - and any help much appreciated.
You shouldn't check the checkbox, but check the value of the file input field. If it is False, then you can delete the file. Otherwise it is the uploaded file. See: https://github.com/django/django/blob/339c01fb7552feb8df125ef7e5420dae04fd913f/django/forms/widgets.py#L434
# False signals to clear any existing value, as opposed to just None
return False
return upload
Let me add here my code that solved the problem - I decided to put this logic to ModelForm.clean():
class Document(models.Model):
upload = models.FileField(upload_to=document_name, blank=True)
class DocumentForm(ModelForm):
def clean(self):
cleaned_data = super(DocumentForm, self).clean()
upload = cleaned_data['upload']
if (upload == False) and self.instance.upload:
if os.path.isfile(self.instance.upload.path):
self.instance.upload.delete(False)

Use local image on django form

I wrote an image upload form which handles file and URL uploads. This is a model form which commits to the database an unpublished image.
class UnpublishedImage(Model(20)):
picture = ImageField(help_text=_('Unpublished picture'), upload_to=settings.UNPUBLISHED_PICTURE_UPLOAD_TO)
That Model(20) gives each model a pid field (20 random slug chars), which I use as a public ID for my models.
The unpublished images work just fine, but now I want to use them, that is, I want to publish them.
class Look(Model(20)):
user = OneToOneField(get_user_model(), editable=False)
title = CharField(max_length=40)
description = TextField(max_length=160)
#image = OneToOneField(UnpublishedImage)
To make this clear, it works in two steps:
The user uploads an image (unpublished)
The next form shows the image and allows to add a description, title, etc.
Now, I can't use OneToOneField to the UnpublishedImage model because I want to delete it from the unpublished table (and storage) as soon as the image is published. How do you recommend doing this?
I have tried ImageField, but I don't know how to give the image to the form.
Note that there's a third form for retrieving unpublished images, so you can use that.
class UnpublishedImagePublishForm(Form):
image = CharField()
def clean_image(self):
# Get the unpublished object
try:
unpublished = UnpublishedImage.objects.get(pid=self.cleaned_data['image'])
except UnpublishedImage.DoesNotExist:
raise ValidationError(_("Image not found"))
return unpublished
This way I can get the image:
# Get the unpublished image
unpublished = UnpublishedImagePublishForm(request.DATA)
if not unpublished.is_valid():
return Response(unpublished.errors, status=HTTP_422_UNPROCESSABLE_ENTITY)
# Get the unpublished image instance
image = unpublished.cleaned_data['image']
Thanks in advance.

Djangothumbnails app issue

I an using this plugin to generate thumbnails. But somhow I couldn't make it work. The models work well, as images can be uploaded from the admin interface, even thumbnails get generated. I uploaded an image named "myphoto.jpg". The view I have is this.
def mainpage(request,slug):
page = get_object_or_404(MainPage, slug=slug)
image = get_object_or_404(Image)
return direct_to_template(request, 'flatpage.html',
extra_context={
'page':page,
'image':image,
})
I have defined the class in models as "Image". I had this in the template:
<img src="{% image.photo.myphoto_125x125 %}"> But the template shows error.
This is my model:
class Image(models.Model):
title = models.CharField(max_length=100)
photo = ImageWithThumbsField(upload_to='images/', sizes=((125,125),(200,200)))
# second_photo = ImageWithThumbsField(upload_to='site_media/images')
def __unicode__(self):
return self.title
The second field, "second_photo" I have commented out as it created duplicate copy of the main image. Even I am looking for a way to create entry for actual unsized image in the first field itself.
I havent tried this app, but I am using PIL to create thumbnail versions of uploaded images, and using a def in the model to retrieve the path to the thumbnail for display. This may be more of a manual approach than you are looking for but it works ok for me. You can override the save method on your model (which has your FileField) or send a post_save signal to a def to create the thumbnail.
But curious to know if this app you are using adds some useful functionality over this manual approach.
Somehow I got it working. Instead of creating a separate class, I used this line photo = ImageWithThumbsField(blank=True, upload_to='images/', sizes=((125,125),(200,200))) in my blog class. And I used the line {{% post.photo.url_125x124 %} in my index.html template.

Django - FileField and images

I'm trying to create some kind of 'media manager' model which will allow the user to upload different kings of media (images, swfs, pdfs) similar to the way WordPress does. My media model looks something like this:
class Media(models.Model):
id = models.AutoField(primary_key=True)
url = models.FileField(upload_to="uploads")
mimetype = models.CharField(max_length=64, editable=False)
created = models.DateTimeField(auto_now_add=True, editable=False)
When a user uploads a file, I want to first determine what kind of file it is and if it's an image, manipulate it further. I want to be able to to specify the dimensions (crop) of the uploaded image via a view, so when I call the .save() method, the model will resize and crop the image, upload it and populate the database with the url to the file.
I also want to ensure that the upload of the image is done AFTER the post processing (cropping etc), I have no need to keep the original file.
So the question I am asking is how do I got about passing parameters to the FileFields save method (so I can pass dynamic properties for image post processing) and how can I ensure the post processing is done BEFORE the image is uploaded?
Edit: When I say before the image is uploaded, I mean before it's saved to it's final destination. I understand the image has to go int othe tmp folder first before I can post process it. Sorry for the misleading question.
Hope someone can help :)
You cannot do anything before the image is uploaded (because you have nothing to work with).
But if you want modify the image before saving it into db, you can do it in model's save() method, before calling parent's save()
If you are uploading it via admin, override method save_model() in admin.py, ie:
def save_model(self, request, obj, form, change):
file = request.FILES.get('url') # name of field
if file:
# proceed your code
return super(AdminClassName, self).save_model(request, obj, form, change)
Here is my code how to change file before actually upload it. I think you should get my idea
from django.core.files.uploadedfile import InMemoryUploadedFile
#....
#some form
def clean_avatar(self):
av = self.cleaned_data['avatar']
resized = make_avatar(av,65) # My custom function than returns image
return InMemoryUploadedFile(resized, av.field_name, av.name, av.content_type, resized.len, av.charset)
You can read django code for InMemoryUploadedFile "documentation".
And in your resize/crop function you should use StringIO not file to save result
How could the processing be done before the image is uploaded? That doesn't make sense. The server doesn't have any access to the file until you upload it.
If you actually want to handle the file before it's saved, you can write a custom upload handler. You can test there whether the file is an image, then crop it appropriately, before saving. (You'll need the Python Imaging Library for both of those tasks.)