Django: does ImageField need a filepath or an actual image object? - python

Running: Windows 7, Python 3.3, Django 1.6
I'm confused as to how to store an image as part of a table in a Django database. There is a field called ImageField, and here are the Docs.
Question:
What should I pass to the ImageField when constructing the record: a filepath string? A url to an image? Or a byte representation of the image itself? Or is there some way of loading an image into Django and then just passing it a reference (or pointer) to that image object?
The docs say: "By default, ImageField instances are created as varchar(100) columns in your database.", which leads me to think that it wants a file path since it's asking for a string.
The Docs also say that it "Requires the Pillow library.", which I've downloaded but it doesn't specify how to use Pillow for this.
Background: I'm building a REST API through django to send and recieve log files from Selenium tests and store them in a SQL database. Each log file comes with a screenshot, hence the need for an ImageField. Just started using Django a few days ago.

Via imagefield and imagefield-derived forms you upload image to your MEDIA_ROOT.
Imagefield store its a path to image. Check the 'media' part of django documentation, it describes how to store user uploaded images for example.
Imagefield also define some basic proprieties of image like width and height.
In your setting.py file you set:
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
MEDIA_URL = '/media/'
Which said I want store uploaded files in yourproject/media and I want too show them in
www.yoursite.com/media/path_to_image/image.png
Then you can define a class with imagefield.
class YourClass(models.Model):
description = models.CharField(max_length=300, unique=True)
picture = models.ImageField(upload_to='myimages')
So images will be stored in yourproject/media/myimages and availible at
www.yoursite.com/media/myimages/image.png
To create new instance:
from django.core.files import File
from idontknow import YourClass
yournewclass = YourClass(description='abc')
yournewclass.picture.save('name.png', File(open('path_to_pic/image.png', 'r'))

Related

Django: correct way to display dynamic images from arbitrary path

In my django app there is a model with CharField "avatar", storing the filename of object's picture (different for each object). Pictures themselves are stored in certain directory on the same host, but not inside the app directory. Say, django app is in /home/djadmin/myapp and images are in /tmp/avatars.
Objects and images are frequently added/updated/deleted via other process (basically, images are uploaded to my host by ftp).
I need to show these images in django template. Say, if field "avatar" stores "123.jpg" than I have to show image from path /tmp/avatars/123.jpg.
How can I display these images using "img" tag in django template?
I guess addind /tmp/avatars to STATICFILES_DIRS is not an option, because my images are not 'static'.

Django can StdImageField replace default variation?

I have existing Django-based project with some files uploaded.
I need to add a feature to automatically resize new uploaded files to some resolution (200x200). I found a nice library django-stdimage that does what I need.
But on upload it stores original file with its original resolution. And existing code works with the original file instead of resized one.
class Product(models.Model):
name = models.CharField(verbose_name=_('Name'), max_length=64)
image = StdImageField(upload_to='product_images/', verbose_name=_('Image'), blank=True, null=True,
variations={'default': (200, 200)})
I would like to save processed files by the same name as original file. I do not need original file by the way.
I do not want to change all the code where it works with image field - there are complex DRF serializers, some views, forms, templates, etc.
So I would like to get new resized image as before by using myproduct.image - in templates for example.
Is it possible to do without subclassing StdImageField ?
I opened a ticket on the StdImage's page and received an answer..
No, I'm sorry, but nether would this work, nor would I advice you to
do such a thing. It would add implicit behavior. That's something you
might want to avoid long term.
You can always overwrite the field tho and implement your own
behavior. The StdImage code base should be good guidance to implement
your own behavior.

Rendering different image formats in Django template

In my Django project, I have a template where I have to upload an image corresponding to the the dynamic instance. For eg: Corresponding to a Student model, I have a template so that I can serve each student's info(including profile photo) on a unique url i.e. /student/student_X. Now for some students, I have a .jpg image while for others a .png image. Currently I have just hardcoded the template so as to handle only the .jpg images in the following way.
<img src="{{ MEDIA_URL }}students/images/{{ student.slug }}.jpg">
where student is the context passed to the template.
How can I modify this so that if a particular student does not have .jpg image available, .png is served? What if there is a set of multiple image formats?
Read this before going further, as understanding media/static files and their differences is very important in Django.
http://blog.doismellburning.co.uk/2012/06/25/django-and-static-files/
As it is, your method could be greatly simplified. If using a Django ImageField in your model the location of the file is stored in your db and there is NO need to differentiate between image types.
Without knowing how you are storing these files and calling students in the view there's no further way to help, but if you are calling field from a Student model object, you can pass the whole Student to the context variables and call the slug like this-
Media files in Django are files uploaded to a location specified in settings.py, of which the location is stored in the db for easy retrieval.

Django Temporary Images

Hi I have this type of model
class Post(models.Model):
title = models.CharField()
image = models.ImageField()
# other fields
For creating a new post I would a flow like this:
in the new post page 1 the user choose the photo and upload it
(submit)
in the new post page 2 the user can see the photo and fill other fields like 'title'
My question is how to upload a photo and display it in the next page, without creating a new Post object with the image field. Should I save the image in a temporany directory? In this case, how can I keep the reference and use it in the second page?
Thanks.
There are couple of solutions
Define another model to just hold images, and add may be OneToOneField in your Post model. On submitting page1, create instance of this image model and put it in page2 as image field.
With html5 file API, you can refer to local file in image field. So you can show image on page2 using local client side path w/o storing it at server. refer: View image selected from file-system on client-side before upload?
First read the relevant doc so you understant what happens with uploaded files:
https://docs.djangoproject.com/en/dev/topics/http/file-uploads/
The simplest solution IMHO would be to
1/ save the uploaded file in some temporary directory - just make sure you can serve the content one way or another (either directly thru the front webserver, or thru a custom view if you want more control on who can access this content),
2/ pass the temporary file path and url to the "next" view one way or another (hidden form fields, session...).
I use to have table to store images (any files in fact :)). Each image is linked to object (FK) and has status - Draft, Approved, Deleted. So I don't use temporary directory, just change status in table of images.

Django upload_to outside of MEDIA_ROOT

My deployment script overwrites the media and source directories which means I have to move the uploads directory out of the media directory, and replace it after the upload has been extracted.
How can I instruct django to upload to /uploads/ instead of /media/?
So far I keep getting django Suspicious Operation errors! :(
I suppose another solution might be a symlink?
Many thanks,
Toby.
I did the following:
from django.core.files.storage import FileSystemStorage
upload_storage = FileSystemStorage(location=UPLOAD_ROOT, base_url='/uploads')
image = models.ImageField(upload_to='/images', storage=upload_storage)
UPLOAD_ROOT is defined in my settings.py file: /foo/bar/webfolder/uploads
While the accepted answer is probably what you want, we now have the option with django 3.1 that we can decide which storage to use at runtime by passing a function to the storage argument of an ImageField or FileField.
def select_storage():
return MyLocalStorage() if settings.DEBUG else MyRemoteStorage()
class MyModel(models.Model):
my_file = models.FileField(storage=select_storage)
Have a look at the official docs.
Please note that the current accepted answer writes the actual value of the variable UPLOAD_ROOT to the migration file. This doesn't produce any SQL when you apply it to the database but may be confusing if you change that setting frequently.

Categories

Resources