Django ImageField Creating New Folder by ID on upload? - django

I'm Currently developing a app with a ManyToMany ImageField Relantionship . I want to have the ImageField save all images to a specific folder based on the ID of the Relantionship.
I want to have something like this.
class PostImages(models.Model):
image = models.ImageField(upload_to='Post_Images/post/' + post.id)
class Post(models.Model):
images = models.ManyToManyField(PostImages)
How do I access the post.id to do this ? I mostly want to do this for organization purposes right now cause its on my local machine but also see no reason to change it when I deploy.

E.g. based on FileField^ but the same you can use for ImageField:
def get_file_path(instance, filename):
return instance.created.strftime("folder/%Y/%m/%d/") + instance.post.id
bfile = models.FileField(upload_to=get_file_path, null=True)

Related

Django Admin show Image immediately after upload

maybe this issue is answered elsewhere, but I have no luck of finding it.
Here is my issue:
I have a Django admin site that has an ImageField to upload image look like this
In order to show the uploaded image, I will have to click on Save/ Save and add another/ Save and continue editing.
What I really want is show preview of the picture immediately after I upload it.
Is there anyway to trigger it via ImageField override or somehow?
Any suggestion would be appreciated
You can't do that because you haven't actually uploaded the image yet. When you "choose file" you've basically just told the browser which file you want to upload, but it doesn't get uploaded until you submit the form.
I am using sorl.thumbnail, but you can easily adapt it into django.
Below is Django model class
Class ImageModel(admin.Models):
...
myfield = models.ImageField(_("Image"), upload_to='project/%Y', null=True, blank=True)
...
#property
def image_tag(self):
im = get_thumbnail(self.myfield.file, 'x300', crop='center', quality=99)
return mark_safe('<img src="%s" width="%s" height="%s" />' % (im.url, im.width, im.height))

Django saving, deleting and viewing user uploaded media with same name

I have a profile app, where users can upload a profile picture. I save the picture with the user's username eg. ifakih.jpg. If that file already exists, and they want to change their profile picture, I delete the old one and replace it with the new one. I can see the change in my directory. The old ifakih.jpg is replaced with the new one. However, my website still uses the old image. If I go to the admin and check the imagefield for that user, it points to the correct directory and image, but the content is wrong.
Models.py:
class Profile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
name = models.CharField(max_length=64,blank=True)
profilePic = models.ImageField(blank=True, null=True, upload_to= path_and_rename)
phoneNumber = models.CharField(max_length=12,blank=True)
streetAddress = models.CharField(max_length=64,blank=True)
#receiver(pre_delete, sender=Profile)
def post_delete(sender, instance, **kwargs):
"""
Deleting the specific image of a Post after delete it
"""
if instance.profilePic:
if os.path.isfile(instance.profilePic.path):
os.remove(instance.profilePic.path)
#receiver(pre_save, sender=Profile)
def post_update(sender, instance, **kwargs):
"""
Replacing the specific image of a Post after update
"""
if not instance.pk:
return False
if sender.objects.get(pk=instance.pk).profilePic:
old_image = sender.objects.get(pk=instance.pk).profilePic
new_image = instance.profilePic
if not old_image == new_image:
if os.path.isfile(old_image.path):
os.remove(old_image.path)
else:
return False
This sounds like a problem that comes from the browser caching images.
To see whether it is related to that, try reloading with STRG + F5 to ignore cached files (you can disable the browser cache in the network tab).
You could solve that problem in two ways:
1) You disable caching for your profile pictures so that the browser always loads the image and does not cache at all. This leads to more traffic on your server and also a longer load time of your site. (NOT recommended)
2)You change the file saving behaviour and allow different filenames. This way the browser will load the image for the first request and then can use it's cache. An ImageField will also generate you a unique name while saving. (Preferred)

Use local image on django form

I wrote an image upload form which handles file and URL uploads. This is a model form which commits to the database an unpublished image.
class UnpublishedImage(Model(20)):
picture = ImageField(help_text=_('Unpublished picture'), upload_to=settings.UNPUBLISHED_PICTURE_UPLOAD_TO)
That Model(20) gives each model a pid field (20 random slug chars), which I use as a public ID for my models.
The unpublished images work just fine, but now I want to use them, that is, I want to publish them.
class Look(Model(20)):
user = OneToOneField(get_user_model(), editable=False)
title = CharField(max_length=40)
description = TextField(max_length=160)
#image = OneToOneField(UnpublishedImage)
To make this clear, it works in two steps:
The user uploads an image (unpublished)
The next form shows the image and allows to add a description, title, etc.
Now, I can't use OneToOneField to the UnpublishedImage model because I want to delete it from the unpublished table (and storage) as soon as the image is published. How do you recommend doing this?
I have tried ImageField, but I don't know how to give the image to the form.
Note that there's a third form for retrieving unpublished images, so you can use that.
class UnpublishedImagePublishForm(Form):
image = CharField()
def clean_image(self):
# Get the unpublished object
try:
unpublished = UnpublishedImage.objects.get(pid=self.cleaned_data['image'])
except UnpublishedImage.DoesNotExist:
raise ValidationError(_("Image not found"))
return unpublished
This way I can get the image:
# Get the unpublished image
unpublished = UnpublishedImagePublishForm(request.DATA)
if not unpublished.is_valid():
return Response(unpublished.errors, status=HTTP_422_UNPROCESSABLE_ENTITY)
# Get the unpublished image instance
image = unpublished.cleaned_data['image']
Thanks in advance.

django database

I am designing a website using django. The idea of a website is to have photographers and each photographer would have an album or more albums and each album would have one or more photo/photos. Currently I have:
class Photo(models.Model):
name=models.ForeignKey('Album')
p=models.ImageField()
def __unicode__(self):
return self.name
class Album(models.Model):
name=models.ForeignKey('Photographer')
def __unicode__(self):
return self.name
class Photographer(models.Model):
name=models.ForeignKey('User')
def __unicode__(self):
return self.name
The question is if you have the same design would you create a directory for each photographer and for each album you would create another directory in the parent directory and then store the photos in that album's directory or store them in the database. I know that is a newbie question but I really need help. If you have other design to make it easier on me please let me know.
Thanks in advance,
Abdul
Use the imagefield to store all the photos at one place and even better store them in cloud storage services. And as to regarding the relation have ForeignKeys in Photo model relating to Album and Photographer. Than use reverse relationship to find out the photos of each album or Photographer.
Your code might look like this`
class Photo(models.Model):
image = ImageField(upload_to="whereever you want to")
album = ForeignKey(Album)
photographer=ForeignKey(Photographer)
and after you get a particular album you can use
Album.set_all and photographer.set_all to get all the photos of a particular album or photographer
`
Yes, store the photos directly in the file system, rather than database. This is a common practise which makes sense for many reasons, mostly related to performance.
If you expect to have thousends of photos then dont keep them one directory, cause that can cause performance issues on popular systems. Instead, design a simple hierarchy appropriate for your application.
There is no need to create directories for photographer or an album. That is what databases are for. You can have one giant folder (specified in upload_to) which will contain all uploaded images for all photographers and albums and then its up for a db to keep track which photos belong to what photographer/album.
By the way you should specify upload_to parameter for ImageField:
models.ImageField(upload_to='images/')
If you really want to create folders for each album, you can pass a function to upload_to parameter and add whatever logic you want there... more about that in the docs here.

Djangothumbnails app issue

I an using this plugin to generate thumbnails. But somhow I couldn't make it work. The models work well, as images can be uploaded from the admin interface, even thumbnails get generated. I uploaded an image named "myphoto.jpg". The view I have is this.
def mainpage(request,slug):
page = get_object_or_404(MainPage, slug=slug)
image = get_object_or_404(Image)
return direct_to_template(request, 'flatpage.html',
extra_context={
'page':page,
'image':image,
})
I have defined the class in models as "Image". I had this in the template:
<img src="{% image.photo.myphoto_125x125 %}"> But the template shows error.
This is my model:
class Image(models.Model):
title = models.CharField(max_length=100)
photo = ImageWithThumbsField(upload_to='images/', sizes=((125,125),(200,200)))
# second_photo = ImageWithThumbsField(upload_to='site_media/images')
def __unicode__(self):
return self.title
The second field, "second_photo" I have commented out as it created duplicate copy of the main image. Even I am looking for a way to create entry for actual unsized image in the first field itself.
I havent tried this app, but I am using PIL to create thumbnail versions of uploaded images, and using a def in the model to retrieve the path to the thumbnail for display. This may be more of a manual approach than you are looking for but it works ok for me. You can override the save method on your model (which has your FileField) or send a post_save signal to a def to create the thumbnail.
But curious to know if this app you are using adds some useful functionality over this manual approach.
Somehow I got it working. Instead of creating a separate class, I used this line photo = ImageWithThumbsField(blank=True, upload_to='images/', sizes=((125,125),(200,200))) in my blog class. And I used the line {{% post.photo.url_125x124 %} in my index.html template.