How can I serve an image in django? - django

I have a binary field to save images
photograph = models.BinaryField(default=None)
In my form, I save the image
photograph = cd['photograph'].file.getvalue(),
)
In My view
f = open('my.jpeg', 'bw')
myfile = File(f)
myfile.write(student.photograph)
filepath = os.path.abspath(os.path.realpath('my.jpeg'))
context['urls'] = filepath
return render(request, 'dashboard.html', context)
The image is saved to the database, it is being retrieved successfully.
Screenshot of the image being saved successfully
My template
The HTML in the template renders well.
If I copy the HTML into a local file, the image appears well and good.
However, the image doesn't load properly when I use django.
Right click > copy image address gives me this: about:blank#blocked
Is it a security or a permissions issue?

After much research, this is what I found.
in HTML
<img src = "data/image:jpeg;base64, {{base64_string}}/>
in view
from django.http import urlsafe_b64encode
return render(request, 'template.html', {'base64_string' : urlsafe_b64encode(myobject.photograph)
This works for development. For production, I guess static files could be served the django way.

Related

Why are uploaded images via Django admin not showing up in the production server?

I have the following model field
logo = models.ImageField(upload_to=municipality_logo_file_name)
and function that uploads the image to the desired location.
def municipality_logo_file_name(instance, filename):
name, extension = os.path.splitext(filename)
return os.path.join('municipality', 'logo', str(uuid.uuid4()) + extension.lower())
In the development mode, a file uploads correctly to for example /media/municipality/logo/1e3cc24a-841b-4577-aa59-b53e5b10420b.png and then displays correctly in the template using
<img src="{{ municipality.logo.url }}" alt="Logo obce" style="max-height: 8rem; width: auto">
In the production, file uploads well, but does not display in the template and the url cannot be followed to display image, the response is
Not Found
The requested resource was not found on this server.
Using IIS and wfastcgi.py.
Any hint as to why this might be happening would be much appreciated.
Try this:
from django.conf import settings
from django.db import models
class Image(models.Model)
image = models.ImageField('Image', upload_to='video-image/')
#property
def image_url(self):
return '%s%s' % (settings.HOST, self.image.url) if self.image else ''

Send PIL image to front without saving it

I'm learning flask and i got stuck in this part.
I want to send a image to a img HTML tag without saving it...
here is where i got so far
PYTHON
def serve_pil_image(pil_img):
img_io = BytesIO()
pil_img.save(img_io, 'JPEG', quality=70)
img_io.seek(0)
return send_file(img_io, mimetype='image/jpeg')
#app.route('/upload', methods=["POST"])
def upload():
target = os.path.join(APP_ROOT, 'static/images')
# create image directory if not found
if not os.path.isdir(target):
os.mkdir(target)
# retrieve file from HTML -- NO SAVING
for upload in request.files.getlist("file"):
print('Getting ', upload)
img = Image.open(upload)
return render_template('processing.html')
#app.route('/static/images')
def serve_img():
img = poster
return serve_pil_image(img)
HTML
<img src="{{ url_for('serve_img', filename=img) }}" class="figure-img img-fluid rounded">
If you know a little JavaScript you could create a url within the window using createObjectURL. Store the blob content that got sent by Flask.send_file in the created object. Get a reference to the image tag, and make it point to the in memory url.

Django - Custom file/Image upload getting file path on upload ? process images on upload?

I have a Django app where users would upload Images and certain functions would take the image file path to process them and save the result in the same model.
all of this would happen in the file upload view the problem is My functions take the file path which isn't created/committed in the DB yet as I don't save before calling those functions.
I tried overriding the save method in the models.py and it didn't work so how can I call the functions after the upload in a convenient way ??
here's the function:
# The view for analysing images
def upload_view(request,pk=None):
patient = get_object_or_404(Patient,pk=pk)
if request.method == 'POST':
form = forms.ImageForm(request.POST,request.FILES)
if form.is_valid():
image = form.save(commit=False)
image.patient = patient
image.enhanced = main(image.original.path)
image.segmented = segment(image.enhanced.path)
image.enhanced.name = image.enhanced.path.split('media')[1]
image.segmented.name = image.enhanced.path.split('media')[1]
messages.success(request,"Image added successfully!")
image.save()
return HttpResponseRedirect(reverse_lazy('patients:patient_detail', kwargs={'pk' : image.patient.pk}))
else:
form = forms.ImageForm()
return render(request, 'patients/upload.html', {'form': form})
else:
form = forms.ImageForm()
return render(request, 'patients/upload.html', {'form': form})
image.original is the uploaded image
the problem is the file path isn't passed correctly and the functions return errors bec of that. (it worked when I made the processing in a different view where it was accessed after the upload)
Before you call save() on your model, the path to your image doesn't exist, or is temporary. You can fix this by first creating the model from the form, no need for commit=False, assuming main and segment are PIL based functions that return images, you can use the ImageField.save() method to set the name at the same time:
if form.is_valid():
image = form.save() # this creates the model, the upload paths are created here!
image.patient = patient
image.enhanced.save("enhanced_" + image.original.name, main(image.original.path)) # I made this up to avoid conflicts in your storage
image.segmented.save("segmented_" + image.original.name, segment(image.enhanced.path))
image.save() # this updates the model with the new images
messages.success(request,"Image added successfully!") # I moved this here, more accurate, in case save fails....
return HttpResponseRedirect(reverse_lazy('patients:patient_detail', kwargs={'pk' : image.patient.pk}))
As you can see, you need two hits to the database to save your images. This assumes that enhanced and segmented fields are not required in the model.
Also, because image transformation is an expensive task, I'd check how to get this out of the request cycle, by using something like Celery or Django-RQ, that way, your app can still service request while making the transformations on the background.

How to find absolute path of uploaded image - Django 1.11

I have a django form in which the user can upload an image that will then be displayed on a page. After the form request is submitted, I'm trying to return an httpresponse to the user of the uploaded image using the following code:
image_data = open("/path/to/my/image.png", "rb").read()
return HttpResponse(image_data, content_type="image/png")
The issue is that I can't get the absolute path from image submitted in the form request. By doing the following, I can get the name of the image, but not the local path to it:
name = ""
for filename, file in request.FILES.iteritems():
name = request.FILES[filename]
imageFileName = name
I've tried using the function file_to_string() based on an SO post, but it looks like the function is deprecated now. How can I get the absolute file path so I can pass it to the open function to return the image?
models.py
class PhotoUploader(models.Model):
title = models.CharField(max_length =120)
image = models.ImageField()
Here the solutions:
once you save the image,then you may got the path like that:
instance = PhotoUploader.objects.get(id=instance_id);
image_full_path = instance.image.path
image_data = open(image_full_path, "rb").read()
return HttpResponse(image_data, content_type="image/png")
"image_full_path" this should be your uploaded image full path.

Storing Images on App Engine using Django

I'm trying to upload and save a resized image in a db.BlobProperty field on Google App Engine using Django.
the relevant part of my view that process the request looks like this:
image = images.resize(request.POST.get('image'), 100, 100)
recipe.large_image = db.Blob(image)
recipe.put()
Which seems like it would be the logical django equivalent of the example in the docs:
from google.appengine.api import images
class Guestbook(webapp.RequestHandler):
def post(self):
greeting = Greeting()
if users.get_current_user():
greeting.author = users.get_current_user()
greeting.content = self.request.get("content")
avatar = images.resize(self.request.get("img"), 32, 32)
greeting.avatar = db.Blob(avatar)
greeting.put()
self.redirect('/')
(source: http://code.google.com/appengine/docs/python/images/usingimages.html#Transform)
But, I keep getting an error that says: NotImageError / Empty image data.
and refers to this line:
image = images.resize(request.POST.get('image'), 100, 100)
I'm having trouble getting to the image data. Seems like it's not being uploaded but I can't figure out why. My form has the enctype="multipart/form-data" and all that. I think something's wrong with how I'm referring to the image data. "request.POST.get('image')" but I can't figure out how else to reference it. Any ideas?
Thanks in advance.
After some guidance from "hcalves" I figured out the problem. First of all, the default version of Django that comes bundled with App Engine is version 0.96 and how the framework handles uploaded files has changed since then. However in order to maintain compatibility with older apps you have to explicitly tell App Engine to use Django 1.1 like this:
from google.appengine.dist import use_library
use_library('django', '1.1')
You can read more about that in the app engine docs.
Ok, so here's the solution:
from google.appengine.api import images
image = request.FILES['large_image'].read()
recipe.large_image = db.Blob(images.resize(image, 480))
recipe.put()
Then, to serve the dynamic images back again from the datastore, build a handler for images like this:
from django.http import HttpResponse, HttpResponseRedirect
def recipe_image(request,key_name):
recipe = Recipe.get_by_key_name(key_name)
if recipe.large_image:
image = recipe.large_image
else:
return HttpResponseRedirect("/static/image_not_found.png")
#build your response
response = HttpResponse(image)
# set the content type to png because that's what the Google images api
# stores modified images as by default
response['Content-Type'] = 'image/png'
# set some reasonable cache headers unless you want the image pulled on every request
response['Cache-Control'] = 'max-age=7200'
return response
You access uploaded data via request.FILES['field_name'].
http://docs.djangoproject.com/en/dev/topics/http/file-uploads/
Reading more about Google's Image API, seems to me you should be doing something like this:
from google.appengine.api import images
image = Image(request.FILES['image'].read())
image = image.resize(100, 100)
recipe.large_image = db.Blob(image)
recipe.put()
request.FILES['image'].read() should work because it's supposed to be a Django's UploadedFile instance.