'str' object has no attribute 'chunks' - django

I have this error when try to save image in folder and in mongo db
how i can solve it
def save_img_field(value):
# Save image file to the static/img folder
image_path = save_image_to_folder(value)
# Save image to MongoDB using GridFS
image_id = fs.put(value, filename=value, content_type=value.content_type)
# Return the image id and path for storage in MongoDB and Django folder
return {'id': str(image_id), 'path': image_path}
def save_image_to_folder(value):
# Create the file path to save the image in the Django static/img folder
image_name = value
image_path = f'decapolis/static/img/{image_name}'
# Open the image file and save it to the folder
with open(image_path, 'wb+') as destination:
for chunk in value.chunks():
destination.write(chunk)
# Return the image path
return image_path
am try to solve it in many way but not working

While saving to a file, add check wheter it is a string or an image:
with open(image_path, 'wb+') as destination:
if type(value) == str:
destination.write(value.encode()) # or whatever you actually want to do if it's a string
else:
for chunk in value.chunks():
destination.write(chunk)

Related

Django - Converting a Binary stream to an Image

I am trying to obtain an image from a url and return it to the ModelAdmin to display it in a new column of the table.
I tried the following code in admin.py file:
def new_field(self, obj):
r = requests.get('https://abcd.com/image')
return r.content
The code is not giving me any error but it's returning a long binary string instead of the image itself.
How can I pass the image itself, or convert the binary content to an image?
You do not need download image if you wont only show it.
def new_field(self, obj):
url = 'https://abcd.com/image'
return '<img src="{}" />'.format(url)
new_field.allow_tags = True # it is important!!!
You can make use of a NamedTemporaryFile [GitHub] here. For example:
from django.core.files import File
from django.core.files.temp import NamedTemporaryFile
def store_image_from_source(self, obj):
img = NamedTemporaryFile()
r = requests.get('https://abcd.com/image')
img.write(r.content)
img.flush()
file = File(img)
obj.my_img_attr.save('filename.jpeg', file, save=True)
Here 'filename.jpeg' is thus te name of the file, as if you would have uploaded a file with that name with a ModelForm.

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.

Upload Image to Amazon S3 with Flask-admin

I am using Flask-Admin and is very happy with it. However, the sample in Flask-Admin only provides to upload the image to static folder. Is it possible to upload it to S3 directly with Flask-Admin? Thanks.
Regards
Alex
Thanks for your sample code, Alex Chan. I needed this functionality too, so I decided to write more complete S3FileUploadField and S3ImageUploadField classes, based on your code and various other snippets.
You can find my code at:
https://github.com/Jaza/flask-admin-s3-upload
Also up on pypi, so you can install with:
pip install flask-admin-s3-upload
I've documentated a basic usage example in the readme (can see it on the github project page). Hope this helps, for anyone else who needs S3 file uploads in flask-admin.
Here it is but not clean the code..
import os
import os.path as op
import cStringIO
import logging
import config
from flask import url_for
from werkzeug import secure_filename
from werkzeug.datastructures import FileStorage
import boto
from boto.s3.key import Key
from wtforms import ValidationError, fields
from wtforms.widgets import HTMLString, html_params
from flask.ext.admin.babel import gettext
from flask.ext.admin._compat import string_types, urljoin
from flask.ext.admin.form.upload import ImageUploadField
try:
from PIL import Image, ImageOps
except ImportError:
Image = None
ImageOps = None
__all__ = ['FileUploadInput', 'FileUploadField',
'ImageUploadInput', 'ImageUploadField',
'namegen_filename', 'thumbgen_filename']
class ImageUploadInput(object):
"""
Renders a image input chooser field.
You can customize `empty_template` and `data_template` members to customize
look and feel.
"""
empty_template = ('<input %(file)s>')
data_template = ('<div class="image-thumbnail">'
' <img %(image)s>'
' <input type="checkbox" name="%(marker)s">Delete</input>'
'</div>'
'<input %(file)s>')
def __call__(self, field, **kwargs):
kwargs.setdefault('id', field.id)
kwargs.setdefault('name', field.name)
args = {
'file': html_params(type='file',
**kwargs),
'marker': '_%s-delete' % field.name
}
if field.data and isinstance(field.data, string_types):
url = self.get_url(field)
args['image'] = html_params(src=url)
template = self.data_template
else:
template = self.empty_template
return HTMLString(template % args)
def get_url(self, field):
if field.thumbnail_size:
filename = field.thumbnail_fn(field.data)
else:
filename = field.data
if field.url_relative_path:
filename = urljoin(field.url_relative_path, filename)
return field.data
#return url_for(field.endpoint, filename=field.data)
class s3ImageUploadField(ImageUploadField):
"""
Image upload field.
Does image validation, thumbnail generation, updating and deleting images.
Requires PIL (or Pillow) to be installed.
"""
widget = ImageUploadInput()
keep_image_formats = ('PNG',)
"""
If field detects that uploaded image is not in this list, it will save image
as PNG.
"""
def __init__(self, label=None, validators=None,
base_path=None, relative_path=None,
namegen=None, allowed_extensions=None,
max_size=None,
thumbgen=None, thumbnail_size=None,
permission=0o666,
url_relative_path=None, endpoint='static',
**kwargs):
"""
Constructor.
:param label:
Display label
:param validators:
Validators
:param base_path:
Absolute path to the directory which will store files
:param relative_path:
Relative path from the directory. Will be prepended to the file name for uploaded files.
Flask-Admin uses `urlparse.urljoin` to generate resulting filename, so make sure you have
trailing slash.
:param namegen:
Function that will generate filename from the model and uploaded file object.
Please note, that model is "dirty" model object, before it was committed to database.
For example::
import os.path as op
def prefix_name(obj, file_data):
parts = op.splitext(file_data.filename)
return secure_filename('file-%s%s' % parts)
class MyForm(BaseForm):
upload = FileUploadField('File', namegen=prefix_name)
:param allowed_extensions:
List of allowed extensions. If not provided, will allow any file.
:param max_size:
Tuple of (width, height, force) or None. If provided, Flask-Admin will
resize image to the desired size.
:param thumbgen:
Thumbnail filename generation function. All thumbnails will be saved as JPEG files,
so there's no need to keep original file extension.
For example::
import os.path as op
def thumb_name(filename):
name, _ = op.splitext(filename)
return secure_filename('%s-thumb.jpg' % name)
class MyForm(BaseForm):
upload = ImageUploadField('File', thumbgen=prefix_name)
:param thumbnail_size:
Tuple or (width, height, force) values. If not provided, thumbnail won't be created.
Width and height is in pixels. If `force` is set to `True`, will try to fit image into dimensions and
keep aspect ratio, otherwise will just resize to target size.
:param url_relative_path:
Relative path from the root of the static directory URL. Only gets used when generating
preview image URLs.
For example, your model might store just file names (`relative_path` set to `None`), but
`base_path` is pointing to subdirectory.
:param endpoint:
Static endpoint for images. Used by widget to display previews. Defaults to 'static'.
"""
# Check if PIL is installed
if Image is None:
raise Exception('PIL library was not found')
self.max_size = max_size
self.thumbnail_fn = thumbgen or thumbgen_filename
self.thumbnail_size = thumbnail_size
self.endpoint = endpoint
self.image = None
self.url_relative_path = url_relative_path
if not allowed_extensions:
allowed_extensions = ('gif', 'jpg', 'jpeg', 'png', 'tiff')
super(ImageUploadField, self).__init__(label, validators,
base_path=base_path,
relative_path=relative_path,
namegen=namegen,
allowed_extensions=allowed_extensions,
permission=permission,
**kwargs)
def pre_validate(self, form):
super(ImageUploadField, self).pre_validate(form)
if self.data and isinstance(self.data, FileStorage):
try:
self.image = Image.open(self.data)
except Exception as e:
raise ValidationError('Invalid image: %s' % e)
# Deletion
def _delete_file(self, filename):
super(ImageUploadField, self)._delete_file(filename)
self._delete_thumbnail(filename)
def _delete_thumbnail(self, filename):
path = self._get_path(self.thumbnail_fn(filename))
if op.exists(path):
os.remove(path)
# Saving
def _save_file(self, data, filename):
path = self._get_path(filename)
if not op.exists(op.dirname(path)):
os.makedirs(os.path.dirname(path), self.permission)
# Figure out format
filename, format = self._get_save_format(filename, self.image)
if self.image and (self.image.format != format or self.max_size):
if self.max_size:
image = self._resize(self.image, self.max_size)
else:
image = self._resize(self.image, (500, 500))
#image = self.image
self._save_image(image, filename, format)
else:
data.seek(0)
data.save(path)
savedUrl=self._save_image(self.image, filename, format)
self._save_thumbnail(data, filename, format)
return savedUrl
def _save_thumbnail(self, data, filename, format):
if self.image and self.thumbnail_size:
path = self._get_path(self.thumbnail_fn(filename))
savedUrl=self._save_image(self._resize(self.image, self.thumbnail_size),
thumbgen_filename(filename),
format)
return savedUrl
def _resize(self, image, size):
(width, height, force) = size
if image.size[0] > width or image.size[1] > height:
if force:
return ImageOps.fit(self.image, (width, height), Image.ANTIALIAS)
else:
thumb = self.image.copy()
thumb.thumbnail((width, height), Image.ANTIALIAS)
return thumb
return image
def _save_image(self, image, path, format='JPEG'):
if image.mode not in ('RGB', 'RGBA'):
image = image.convert('RGBA')
conn =boto.connect_s3( config.AWS_KEY, config.AWS_SECRET,)
bucket = conn.get_bucket("vipbutton")
k = Key(bucket)
k.key= path
tempFile = cStringIO.StringIO()
image.save(tempFile,format)
#image.seek(0)
#tempFile.seek(0)
#k.set_contents_from_string('This is a test of S3')
k.set_contents_from_string(tempFile.getvalue())
k.set_acl('public-read')
#k.set_contents_from_file(tempFile.getValue())
#with open(path, 'wb') as fp:
# image.save(fp, format)
return k.generate_url(expires_in=0, query_auth=False)
def _get_save_format(self, filename, image):
if image.format not in self.keep_image_formats:
name, ext = op.splitext(filename)
filename = '%s.jpg' % name
return filename, 'JPEG'
return filename, image.format
# Helpers
def namegen_filename(obj, file_data):
"""
Generate secure filename for uploaded file.
"""
return secure_filename(file_data.filename)
def thumbgen_filename(filename):
"""
Generate thumbnail name from filename.
"""
name, ext = op.splitext(filename)
return '%s_thumb%s' % (name, ext)

Django file upload with unique name

I try to upload a file in Django by following Django docs.
def handle_uploaded_file(f):
with open('some/file/name.txt', 'wb+') as destination:
for chunk in f.chunks():
destination.write(chunk)
But it overwrites the name.txt file when I upload it. How can I make sure that it has a unique name in that folder? (It may be saved as name(1).txt)
P.S: Django handles it when saving a model with File field. However, I use forms and I need to handle it manually.
Thanks
You'll get a unique id if you use the uuid library
import uuid
def handle_uploaded_file(f):
name = 'some/file/%s.txt' % uuid.uuid1()
with open(name, 'wb+') as destination:
for chunk in f.chunks():
destination.write(chunk)
http://docs.python.org/2/library/uuid.html

Serving Zip file Django

I'm following this solution (Serving dynamically generated ZIP archives in Django) to serve some zip files from django.
The idea is to select the files from a database using some check boxes, but I'm trying to make the example work with just 2 images.
import os
import zipfile
import StringIO
from django.http import HttpResponse
def getfiles(request):
# Files (local path) to put in the .zip
# FIXME: Change this (get paths from DB etc)
filenames = ["/home/../image1.png", "/home/../image2.png"]
# Folder name in ZIP archive which contains the above files
# E.g [thearchive.zip]/somefiles/file2.txt
# FIXME: Set this to something better
zip_subdir = "somefiles"
zip_filename = "%s.zip" % zip_subdir
# Open StringIO to grab in-memory ZIP contents
s = StringIO.StringIO()
# The zip compressor
zf = zipfile.ZipFile(s, "w")
for fpath in filenames:
# Calculate path for file in zip
fdir, fname = os.path.split(fpath)
zip_path = os.path.join(zip_subdir, fname)
# Add file, at correct path
zf.write(fpath, zip_path)
# Must close zip for all contents to be written
zf.close()
# Grab ZIP file from in-memory, make response with correct MIME-type
resp = HttpResponse(s.getvalue(), mimetype = "application/x-zip-compressed")
# ..and correct content-disposition
resp['Content-Disposition'] = 'attachment; filename=%s' % zip_filename
return resp
I wrote the getfile(request) on my views.py and i make a call from the index view
def index(request):
if request.method == 'POST': # If the form has been submitted...
resp = getfiles(request)
form = FilterForm(request.POST) # A form bound to the POST data
# do some validation and get latest_events from database
context = {'latest_events_list': latest_events_list, 'form': form}
return render(request, 'db_interface/index.html', context)
I know the getfile() method is called, because if I put names of unexistents files I got an error, but I dont get any download neither an error if the filenames are correct (I put the full path /home/myuser/xxx/yyy/Project/app/static/app/image1.png).
I tried with the django server and with the apache2/nginx server I have for production
I also tried using content_type = 'application/force-download'
Thanks