I'm actually new to Django. Let's say I have this model as a class
class UserAccount(AbstractBaseUser, PermissionsMixin):
...
profile_photo = models.ImageField(
upload_to='photos/profile-picture', blank=True)
objects = UserAccountManager()
def __str__(self):
return self.email
I want to save the profile_photo attribute as a base64 file (instead of file path). How do I do that?
Context : In my client side (front-end), I can't render the image by getting its file path. So I want to save the image as base64 string in the DB instead of actual image path so that it will be easier to render in the front end
ImageField has "url" property. It's will combine with MEDIA_URL in the project's setting.
Related
I have a model, that on save, it uploads my image to my S3 bucket. But I'm having some trouble when I want to reupload an image with the same name. (Example: when a logo updates it needs to be reuploaded)
Because the image already exists, Django extends the pathname with it's own generated extention to make it unique. We don't want that, we want to delete the existing image before uploading the new image. That way, the extention is no more.
I've tried removing my image first with the pre_save signal, but that just makes my imagefield empty
#receiver(pre_save, sender=geo_models.Logo)
def remove_file_from_s3(sender, instance, using, **kwargs):
instance.png.delete(save=False)
Any way of doing this?
Model:
class Logo(models.Model):
logo_type_choices = Choices(
('ENTITY', _('Entity')),
('BRAND', _('Brand')),
)
class Meta:
verbose_name = _('logo')
verbose_name_plural = _('logos')
png = models.ImageField(
verbose_name='{0} {1}'.format('png', _('image')),
upload_to=get_upload_loc_png,
validators=[validators.validate_png_extension],
storage=storage,
max_length=200,
blank=True,
null=True,
)
logo_type = models.CharField(choices=logo_type_choices, max_length=20)
django-storages has an optional setting AWS_S3_FILE_OVERWRITE.
By default, it is set to True (reference). That is, by default files with the same name will overwrite each other. Set this to False to have extra characters appended.
The usual practice is to define CKEDITOR_UPLOAD_PATH = 'uploads/' in settings.py. But this will save the images in all models in a unique path. Is it possible to assign a different image path to each model?
class BlogModel(models.Model):
......
content = RichTextUploadingField() # image upload to /media/blog/
class NewsModel(models.Model):
......
content = RichTextUploadingField() # image upload to /media/news/
You can assign a path by using FileField upload_to='pathname'
class BlogModel(models.Model)
content = models.FileField(upload_to='blog/')
class NewsModel(models.Model)
content = models.FileField(upload_to='news/')
Blogmodel content will be uploaded to /media/blog/
Newsmodel content will be uploaded to /media/news/
You can also do:
content = models.FileField(upload_to='pathname/%Y/%m/%d/')
Will be saved as /pathname/2019/04/04/
I'm a noob django developer, I can upload images but name of the images have to be changed to image ID or whatever I want.
In addition to this, when I delete entries, images are still resting in the media file but I don't want this.
What I have to add ?
Here is my models.py
from django.db import models
class Flower(models.Model):
name = models.CharField(max_length = 30)
price = models.IntegerField()
image = models.ImageField(upload_to = 'static/media')
def __unicode__(self):
return self.name
To customize the path and filename of where the files are stored, you'll need to define a method for upload_to. Here's an example:
def my_upload_to(instance, filename):
# "instance" is an instance of Flower
# return a path here
return 'my/path/to/storage/' + filename
class Flower(models.Model):
image = models.ImageField(upload_to=my_upload_to)
See https://docs.djangoproject.com/en/dev/ref/models/fields/#filefield
To delete the underlying file, you'll need to make a call manually:
flower = Flower.objects.get(id=1)
flower.image.delete()
You can choose to override your model's delete() method, or use signals pre_delete or post_delete to delete the associated files automatically.
See https://docs.djangoproject.com/en/dev/ref/models/fields/#filefield-and-fieldfile
So ive read over the docs and I have come out a little confused. I have a model as such
class Image(models.Model):
name = models.CharField(max_length=80)
file = models.ImageField(upload_to = 'project_images')
description = models.CharField(max_length=30)
def __unicode__(self):
return self.name
The handling of the file uploads are done through the admin interface, which works but I need to do a few more things to the data based on other fields present when the upload is committed.
Basically the current directory is project_images what i want to do is when saved the images must be placed in ---> project_images/<year>/<month>. The file path saved must reflect this when saved in the database and the filename must also be saved in the name field.
I understand the logic behind doing this;
Check post
Check valid (the ImageField takes care of this already i assume)
Get filename
Get year and month (numbers)
Check if directories exist
If directories dont exist create it, if they do use them
Set the name to the filename
upload and save all
Where am i supposed to specify this? In the model under a save method?
Sorry if this is specified in the docs but this is one area of the docs which just confused me.
Thanks
from django.db import models
import datetime
import os
import uuid
# Create your models here.
def get_file_path(instance,filename):
ext=filename.split('.')[-1]
filename="%s.%s" % (uuid.uuid4(),ext)
return os.path.join(instance.directory_string_var,filename)
class Image(models.Model):
file=models.ImageField(upload_to=get_file_path)
now=datetime.datetime.now()
directory_string_var = 'image/%s/%s/%s/'%(now.year,now.month,now.day)
change your model to above one.
this saves your file with a random name in the folder media/year/month/day.
if you don't want filename to be random just comment out
ext = filename.split('.')[-1] #and
filename="%s.%s" % (uuid.uuid4(),ext)
check this:
how to create year/month/day structure when uploading files with django
So in your model, you can just do:
class Image(models.Model):
name = models.CharField(max_length=80)
file = models.ImageField(upload_to = 'project_images/%Y/%m')
description = models.CharField(max_length=30)
def __unicode__(self):
return self.name
The '%Y/%m' part of upload_to is strftime formatting; '%Y' is the four-digit year and '%m' is the two-digit month
You must check this to:
http://scottbarnham.com/blog/2007/07/31/uploading-images-to-a-dynamic-path-with-django/
I Hope this helped
I'm building a software repository on top of the Django framework. Because it will contain a lot of files, i want it to make some sense when looking at it through a file manager. So i grouped the files first by the URL of a program they belong to and then by first two letters of that URL. Here's how it looks:
The schema looks like this:
class File(models.Model):
# If called like upload_to, don't put a slash in front of the result
# because we already have one in settings.MEDIA_ROOT
def get_absolute_url(self, filename=None):
return '%sfiles/%s/%s/%s' % ('' if filename else '/',
self.download.url[:2],
self.download.url,
filename or self.name)
name = models.FileField(upload_to=get_absolute_url, max_length=255)
size = models.IntegerField()
title = models.CharField(blank=True, max_length=255)
download = models.ForeignKey('Download', related_name='files')
class Download(models.Model):
url = models.SlugField(unique=True, max_length=255)
title = models.CharField(max_length=255)
There is, however, a minor problem: FileField will store the entire generated path instead of just the name, which i would rather like to avoid. Is there any way to override (probably in my own field class) what FileField writes to the database and how it reconstructs the path after loading the raw field?
name = models.FileField(upload_to=get_absolute_url, max_length=255)
upload_to usually looks like this
upload_to ='./files'
It will be stored as ./files/your.file in the db
and as <MEDIA_ROOT>/files/your.file at your disk
You can change the upload_to-String to whatever fits best for you programatically
upload_to ='./files'+'/subdir'
but it should start with './'
FileField-Reference
get_absolute_url() should return a url like http://domain.com/sitemedia/files/your.file
EDIT:
to remove the path from the file name you could do string operations in File.save() like
def save(self, force_insert=False, force_update=False):
self.name = self.name[self.name.rfind('/')+1:]
super(File, self).save(force_insert, force_update)