Use already uploaded image in Django's ImageField - django

Is there an option in ImageField to set the path or an already uploaded image?
My use case is as follows: I want to reutilize the same image in two different content entries. I don't want to upload the image twice or to store two copies of the same image.

Just assign the image field from one model instance to another:
original_entry = Entry.objects.get(pk=1)
another_entry = Entry.objects.get(pk=2)
another_entry.image = original_entry.image
another_entry.save()
new_entry = Entry.objects.create(image=original_entry.image)

Just put an image in it's own model:
class Image(models.Model):
image = models.ImageField(...)
class ModelA(models.Model)
image = models.ForeignKey(Image, null=True, blank=True)
class ModelB(models.Model)
image = models.ForeignKey(Image, null=True, blank=True)

Related

How to get an image from the server with django and graphql?

I already managed to make the mutations to upload, update and print the images. But how can I get the images files on in base64 in the query?
class Image(models.Model):
image = models.ImageField(blank=True, null=True, upload_to="uploads/images")
product = models.ForeignKey(Product, on_delete=models.CASCADE, blank=True, null=True)
I write my own solution.
First I created a new field in the ImageType object to store the image file in base 64. Additionally I validated that the value of the image field existed and the written address was associated with an existing file on the hard disk.
Then when the image is requested a new field called base64file appears with the stored image that can then be decoded in the frontend.
Hope this is helpful to someone. Here is my code:
class ImageType(DjangoObjectType):
class Meta:
model = Image
filter_fields = {'product_id': ['exact'],
interfaces = (relay.Node,)
base64file = graphene.String()
def resolve_base64file(self, info):
if self is not None and self.image and hasattr(self.image, 'url'):
if os.path.isfile(self.image.url):
return base64.b64encode(self.image.read())
else:
return 'File not found'
return ''

Confusion about Imagefield

I am learning Django as a beginner. Commonly speaking(documentation-wise), is Imagefield for photos? What field is then for the image files? (dmg for example). Thank you.
ImageField inherits all attributes and methods from FileField, but also validates that the uploaded object is a valid image using Pillow. It also has two additional optional arguments: height_field and width_field (these are auto-populated with the height and width of the image respectively, each time the model instance is saved).
Example:
class Photo(models.Model):
image = models.ImageField(blank=True, null=True, upload_to='image_collection', height_field='image_height', width_field='image_width', max_length=1000)
image_height = models.PositiveIntegerField(null=True, blank=True, editable=False)
image_width = models.PositiveIntegerField(null=True, blank=True, editable=False)

Django: ManyToMany association not working

models.py
class Gallery(models.Model):
name = models.CharField(max_length=100)
class Image(models.Model):
in_gallery = models.ManyToManyField(Gallery, blank=True)
title = models.CharField(max_length=100)
class ImageInGallery (models.Model):
image = models.ForeignKey(Image, blank=True, null=True, on_delete=models.DO_NOTHING)
gallery = models.ForeignKey(Gallery, blank=True, null=True, on_delete=models.DO_NOTHING)
Click to view the screenshot of my admin page of adding a Gallery
Click to view the screenshot of my admin page of adding an Image
Have a look at the screen shot....
(ignore the fields that I didn't show in models.py code for simplicity) See the difference I have in admin page of adding a Gallery and Image..... I cannot add image to Gallery
How to fix this?
what's the purpose of ImageInGallery ?
You have to use through argument.
Since you define ManyToManyField in Image you already have a bilateral relation.
If you want all galleries related to an image1 instance of Image you can do a :
image1.galleries.all()
If you want images related to gallery1 instance of Gallery, you can do :
galleries.image_set.all()
In documentation, your Gallery is 'Publication' and Image is 'Article'.

Django, select image from previous uploaded images

I have a Post model which has a ImageField.
class Post(models.Model):
headline = models.CharField(max_length=255)
lead = models.TextField(blank=True, null=True)
body = models.TextField(blank=True, null=True)
image = models.ImageField(upload_to="posts", blank=True, null=True, max_length=255)
In my ModelForm, the file input for the image works perfectly, but I was wondering how to let the user choose between uploading a new image, or selecting one from all the images that have been previously uploaded to the site.
Any pointers?
In order to do that define another model Image and then create a foreign key from Post to Image. When creating a new post, you can either select an existing image or upload a new one and then select it.

How to copy an object from one model to another model

Each user has many albums, and each album has its many photos. And each user has one set background image to hold its many images. Similarly, a user has one set of profile picture to hold its many images.
These are my models:
class UserProfile(models.Model):
user = models.OneToOneField(User)
permanent_address = models.TextField()
temporary_address = models.TextField()
profile_pic = models.ForeignKey(ProfilePicture)
background_pic = models.ForeignKey(BackgroundImage)
class Album(models.Model):
user = models.ForeignKey(User)
name = models.CharField(max_length=200)
pub_date = models.DateTimeField(default=datetime.now)
class Photo(models.Model):
album = models.ForeignKey(Album, default=3)
image = models.ImageField(upload_to=get_upload_file_name)
caption = models.CharField(max_length=200)
pub_date = models.DateTimeField(default=datetime.now)
class BackgroundImage(models.Model):
user = models.ForeignKey(User)
image = models.ImageField(upload_to=get_upload_file_name)
caption = models.CharField(max_length=200)
pub_date = models.DateTimeField(default=datetime.now)
class ProfilePicture(models.Model):
user = models.ForeignKey(User)
image = models.ImageField(upload_to=get_upload_file_name)
caption = models.CharField(max_length=200)
pub_date = models.DateTimeField(default=datetime.now)
Eg: I tried doing this: to let the user copy one image from ProfilePicture to Background Image, but didn't work:
# Get the user
>>>m = User.objects.get(username='m')
# Get its set of Profile pictures
>>>m_pro_set = m.profilepicture_set.all()
>>>m_pro_set
[<ProfilePicture: pro_mik>]
# Get its set of Background images
>>>m_back_set = m.backgroundimage_set.all()
>>>m_back_set
[<BackgroundImage: bg_mik>]
# Get an image object from Profile picture of the user
>>>m_pro_1 = m.profilepicture_set.get(id=2)
>>>m_pro_1
<ProfilePicture: pro_mik>
# Get an image object from Background image of the user
>>>m_back_1 = m.backgroundimage_set.get(id=2)
>>>m_back_1
<BackgroundImage: bg_mik>
# So, I tried to copy one image from BackgroundImage of a user to ProfilePicture
>>>m_pro_set.objects.create(m_back_1)
File "<console>", line 1, object has attribute 'objects'
AttributeError: 'QuerySet' object has no attribute 'objects'
So my question is, how to copy an objects from one model to another? Any advice will be much appreciated.
You'll need to copy the properties of one object to another object. create is used when you want to create a new instance, not when you want to update a specific instance.
m_pro = m_pro_set[0] # m_pro_set is a list and need to get the specific instance
m_pro.image = m_back_1.image
m_pro.caption = m_back_1.caption
m_pro.pub_date = m_back_1.pub_date
m_pro.save()
Alternatively you can create a method on ProfilePicture if this is a common operation to contain this functionality.
class ProfilePicture(models.Model):
user = models.ForeignKey(User)
image = models.ImageField(upload_to=get_upload_file_name)
caption = models.CharField(max_length=200)
pub_date = models.DateTimeField(default=datetime.now)
def update(self, bg_img):
self.image = bg_img.image
self.caption = bg_img.caption
self.pub_date = bg_img.pub_date
self.save()
So you would just need to call m_pro_1.update(m_back_1) if we wanted to make m_pro_1 have the same properties as m_back_1
Also, if you wanted to create a new instance, I'd suggest using a classmethod like the following
class ProfilePicture(models.Model):
...
#classmethod
def create_from_bg(cls, bg_img):
img = cls(user=bg_img.user, image=bg_img.image, caption=bg_img.caption, pub_date=bg_img.pub_date)
img.save()
return img
#classmethod
def create_from_photo(cls, photo):
img = cls(user=photo.album.user, image=photo.image, caption=photo.caption, pub_date=photo.pub_date)
img.save()
return img
This creates a new ProfilePicture and is used: profile_pic = ProfilePicture.create_from_bg(m_back_1)