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.
Related
I've been working on Django project. Currently, user can upload only one image but now I want to change it so user can upload some images.
models.py is like this.
class Entry(models.Model):
photo = models.ImageField(...)
I am thinking of just adding photo2 and photo3 inside Entry model. But I'm wondering if there's a better way to do it. I don't want to delete images that are already uploaded. Anyone who could give me tips? Also, I don't like the file upload form's design and some people use just button-like form. I also want to know how to create button-like form.
Create new model called 'Photo'.
Create relationship from 'Entry' to 'Photo'.
If you want to use photos that related with Entry record, you need to use select_related() function
Also you can find button-like upload form here.
I have 2 models Listing and Image, where a listing can have multiple images.
class Listing(models.Model):
title = models.CharField(max_length=100, blank=False)
class ListingImage(models.Model):
listing = models.ForeignKey(Listing, on_delete=models.CASCADE, related_name='images')
image = models.ImageField(blank=True)
Ideally, I wanted to create such listings on a single page e.g. fill in all form information AND add images on the same page.
It seems that this is not possible (if it's please let me know, but note that dropzone.js is Ajax) to handle 2 forms with a single view and I have made the following workarounds:
Create listings first, add 2nd step to add listings to created
model
Create a placeholder listing, add images to it (via Ajax)
and on form submit, change the placeholder information.
Which method is better?
views.py
def add_image(request):
# process images: problem we have no listing_instance to add them to
if request.method == 'POST':
form = ListingImageForm(request.POST, request.FILES)
if form.is_valid():
ListingImage.objects.create(pk=None, listing=listing_instance)
return HttpResponse(
json.dumps({
"result": True,
}),
content_type="application/json"
)
I'm looking for methodology advice. For example, to create a listing with images, do I need to first create the listing and then add images (2 steps) or add images first and listing information? My problem is that if I do that, the listing is not yet created when I add the images using Ajax.
I'll propose my solution which I've implemented in my projects and works like a charm.
form is rendered, dropzone.js initialized
images are submitted and uploaded to the defined endpoint (url), here django view saves uploaded file (as a model), returns saved image pk (or other unique identifier).
client front-end receives saved image pk and stores in the hidden input (for ex. named images) with some kind of protocol (for ex. pk1::pk2::pk3)
once form is submitted, django form validation has passed, you are processing input value with image pks and get entries from db:
images = ListingImage.objects.filter(pk__in=request.POST.get('images').split('::'))
I strongly recommend to apply more validation to images value
This query will give you all user uploaded images for submitted form, and finally you will update ListingImage entries to link Listing entry
images.update(listing=newly_created_listing_entry)
In addition, to avoid db bloating, I run cron job every 1 day to clean images which are not linked to any form (in case user abandoned form submission)
hope, this helps
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.
Trying to write a website that will allow users to upload photos, and so far, I've been using the Flask-Uploads library (docs here)
Used in the example in the docs is a class Photo that seems fairly critical:
rec = Photo(filename=filename, user=g.user.id)
rec.store()
...
photo = Photo.load(id)
Problem being that the name Photo doesn't exist in flask.ext.uploads and I'm not sure where to upload it from.
Has anyone else experienced the same issue?
Photo is a model class that you'd need to define. If you take a look at the example application you'll see a class named Post.
post = Post(title=title, caption=caption, filename=filename)
post.id = unique_id()
post.store()
This particular example was made using Flask-CouchDB, but you can use any data store you'd like. You'll just need to replace the lines that save the Photo or Post with however you save references to uploaded files in your application.
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.