Django - ImageField with multiple images - django

I have a model that has an ImageField. I want users to be able to upload multiple images for an object of the model - not only a single image. How can this be done? Whether with and image field or another approach.

You cannot store several images in one ImageField.
One solution for this problem would be to create an additional model (I called it "Attachment" for my social network pet project, call your's whatever should suit you) and have it reference the original model in a Foreign key. That way you can upload as many images as you want and create an instance of that new model for each new image.
Example Attachment model:
class Attachment(DatetimeCreatedMixin, AuthorMixin):
class AttachmentType(models.TextChoices):
PHOTO = "Photo", _("Photo")
VIDEO = "Video", _("Video")
file = models.ImageField('Attachment', upload_to='attachments/')
file_type = models.CharField('File type', choices=AttachmentType.choices, max_length=10)
publication = models.ForeignKey(TheOriginalModelYouUsedImageFieldIn, on_delete=models.CASCADE, verbose_name='Model that uses the image field')
class Meta:
verbose_name = 'Attachment'
verbose_name_plural = 'Attachments'

Related

Saving images names into the database - Django

I have the folllowing class model in my Django website:
class Buy(models.Model):
category = models.ForeignKey(Category, related_name='sell', on_delete=models.CASCADE)
title = models.CharField(max_length=100)
image = models.FileField()
image2 = models.FileField(blank=True)
description = models.CharField(max_length=300)
date = models.DateField(default=timezone.now)
buy_price = models.DecimalField(max_digits=6, decimal_places=2)
sell_price = models.DecimalField(max_digits=6, decimal_places=2)
seller = models.ForeignKey(Seller, on_delete=models.PROTECT)
showcase = models.BooleanField(default=False)
As you can see, I store photos files with 2 fields: image and image2. But now my client requested me to add more photos. My doubt is:
Should I continue adding new fields to this class, for example, image3, image4, image5 and so on? The problem I see: not every records will have so many photos and the most of them will become "empty".
Should I only upload the new photos without saving their names into the database? In this way, the new photos should follow some name related to the image class field. I mean, unique_photo_1.jpg goes inside the image field, unique_photo_2.jpg is not saved into the database but is related to this field, as well as the unique_photo_3.jpg.
What is the best practice?
Thank you!
On #1, the best practice is to follow database normalization principles, and create a separate Image model that relates back to your Buy model. If you anticipate that the images may be reused in several Buy model instances, use many-to-many relationships; otherwise, use many-to-one (i.e. ForeignKey). That means removing image and image2 from your Buy model, and then creating e.g.:
class Image(models.Model):
image = models.FileField()
image_type = models.CharField()
buy = models.ForeignKey(Buy, on_delete=models.PROTECT)
By #2, if you mean you're considering skipping using FileField or ImageField to instead write code that will search for files in some storage space, then that doesn't sound like a good idea, because then you're divorcing your file (meta)data from the rest of your database contents. Using FiledField/ImageField will also make it much easier to use storage backends such as AWS S3.

Django view doesn't save model instances but running the data processing functions correctly?

I have a function that process images that are uploaded by users. I made a view that when entered apply the function on the uploaded images.
models.py
class UploadedImages(models.Model):
patient = models.ForeignKey(Patient,on_delete=models.CASCADE,related_name='images')
pre_analysed = models.FileField(upload_to = user_directory_path ,
verbose_name = 'Image')
class Processed(models.Model):
uploaded_image = models.ForeignKey(UploadedImages,on_delete=models.CASCADE,related_name='processed')
analysedimage = models.ImageField(upload_to=analyses_directory_path,
verbose_name='analysed Image', blank=True)
views.py
def AnalysedDetails(request,pk=None):
Uimage = get_object_or_404(models.UploadedImages,pk=pk)
analysed = models.Processed(uploaded_image=Uimage,analysedimage=main(Uimage.pre_analysed.path))
analysed.save()
return HttpResponse("OK")
but when i check the admin page to see the model it only saves the uploaded image and doesn't save the processed one and when I check the directory i find that only the uploaded image field is saved.
I tried
analysed=models.Processed(uploaded_image=Uimage.pre_analysed,analysedimage=main(Uimage.pre_analysed.path))
but it returns
Cannot assign "":
"Processed.uploaded_image" must be a "UploadedImages" instance
to create new object, theres simple way, using .create(),
see this how to create object
so, it would be
analysed = models.Processed.objects.create(...)
and you don't need save() method if you use this way
to save ImageField programmatically, you can see this or this

Django - Performance between images as fields vs images as ForeignKey model

I have a model called Listing. Users can upload up to 20 photos for each Listing.
My question is: Performance-wise, is it better to create 20 fields for Listing, and leave them blank if the user doesn't fill them, or create a ListingPhoto foreignkey and create 1 ListingPhoto for each uploaded image?
class Listing(models.Model):
img_1 = models.ImageField(blank=True)
img_2 = models.ImageField(blank=True)
...
img_20 = models.ImageField(blank=True)
OR
class Listing(models.Model):
...
class ListingPhoto(models.Model):
listing = models.ForeignKey(Listing, on_delete=models.CASCADE)
photo = = models.ImageField()
Well, using 20 image field will be faster for sure as there is no joins required when you are retrieving these images. But this is not very flexible. You can consider using ArrayField or JSONField to be both flexible and require no joins.

django admin foreign key to file field and many to many field

I have a model Teacher which has following data:
class Teacher(models.Model):
name = models.CharField(max_length=100)
thumbnail = models.ForeignKey(Thumbnail)
class Thumbnail(models.Model):
thumbnail = models.FileField(upload_to=upload_to)
class TeacherAdmin(admin.ModelAdmin):
list_display = ('name',)
Here I want to relate all the thumbnail in my project to Thumbnail field. In my admin it shows me a dropdown of thumbnail while I want to add the thumbnail from admin.
Is it possible that I can upload from admin too?
Also what can I do in the case like :
class Teacher(models.Model):
name = models.CharField(max_length=100)
thumbnail = models.ManyToManyField(Thumbnail)
If I want to add multiple Images.
The only issue I am having is on admin side. Client side can be handles from regular forms.
Need suggestions and Ideas

User-generated fields in Django

I'm building a Djano application which displays a set of images, and a form for each image for recording specific image characteristics. The user initializes a "project", where they specify the set of images that will be displayed for assessment. At project initialization, I'd like to give the user the ability to add custom boolean fields (i.e. a set of checkboxes), but I can't figure out how to build the database models.
For example, a user might initialize my_project with image_A.png, image_B.png and image_C.png for assessment. The default form they'll get for each image lets them choose between PASS, FAIL and UNKNOWN. They might wish to add custom fields like "poorly cropped", "over-exposed" or "blurry" (the idea being that the image could be a global PASS, but small failures, specific to the context of this image set, could still be recorded).
Generally, I'm trying to come up with a way to model user-generated fields in Django.
If I correctly understand, you don't need dynamic model fields, instead you can add model, which contains specific attributes for image in project, something like:
class Image(models.Model):
name = models.CharField()
img = models.ImageField()
class ProjectImage(models.Model):
image = models.ForeignKey('Image')
project = models.ForeignKey('Project')
flag = models.CharField(choices=PASS_FAIL_UNKNOWN)
class ProjectImageTag(models.Model):
project_image = models.ForeignKey(ProjectImage)
value = models.CharField()
class Project(models.Model):
images = models.ManyToManyField('Image', through=ProjectImage)
Also, you can store such tags in json field or postgres hstore field instead of separate table.
EDIT
Variation with predefined keys:
class ProjectImage(models.Model):
image = models.ForeignKey('Image')
project = models.ForeignKey('Project')
flag = models.CharField(choices=PASS_FAIL_UNKNOWN)
class Image(models.Model):
name = models.CharField()
img = models.ImageField()
class Project(models.Model):
images = models.ManyToManyField('Image', through=ProjectImage)
class ProjectImageParams(models.Model):
project_image = models.ForeignKey(ProjectImage, related_name='params')
key = models.CharField()
value = models.BooleanField()
Params of image may be obtained with ProjectImage().params.all(). And yes, django-eav may be a good option.