django save imagefile in static dir - django

I have some images i retrieve from http://image.eveonline.com/ that i want to save. Now part of those will be static, while others might change.
Instead of pulling all static images from their site, i want to do this when they are needed (if they are not saved yet)
How can i tell my model to save the imagefield in static or in media
Example model:
class ItemIcon(models.Model):
item = models.ForeignKey("items.Item")
size = models.IntegerField(choices=settings.IMAGE_SIZES)
url = models.URLField(unique=True) #The url to the evesite
image = models.ImageField(upload_to="static/images/items/")
(this model should be saved in static)

you need to set your MEDIA_URL and MEDIA_ROOT in your settings.py and then define your image field like this:
image = models.ImageField(upload_to="items")
Note that you dont need to add the whole path to upload_to attribute, Django will append the absolute path for you. And you need to have a folder named items inside your media folder.
If you want to save images in STATIC_ROOT, try this:
from django.conf import settings
fs = FileSystemStorage(location=settings.STATIC_ROOT)
class ItemIcon(models.Model):
item = models.ForeignKey("items.Item")
size = models.IntegerField(choices=settings.IMAGE_SIZES)
url = models.URLField(unique=True) #The url to the evesite
image = models.ImageField(upload_to="items",storage=fs)

Related

How to store image in Django - use link or no?

I have field:
image = models.ImageField(
max_length=500,
upload_to='images'
)
and some settings to upload an image to AWS S3 Bucket, where PublicMediaStorage is my custom storage:
PUBLIC_MEDIA_LOCATION = 'media'
AWS_S3_MEDIA_ENDPOINT_URL = env('AWS_S3_MEDIA_ENDPOINT_URL', None)
DEFAULT_FILE_STORAGE = 'new_project.storages.PublicMediaStorage'
I need to store and get my images from database(postgres).
For now my image stores at the database like
here.
And if i write image.url i will get the url of my image(that's why I don't need to store urls of images in my database).
But is it right way? Maybe it will be better to store immediately links at the database? Any solutions?
OP is doing well using ImageField . OP might want to add blank=True so that OP's forms don't require the image.
image = models.ImageField(upload_to='images', blank=True)
The reason to use ImageField is that it checks whether the image is valid and also uploads it to the right location, which is something one wouldn't get with a simple URL. That is why the docs mention it requires the Pillow library.
With regards to the DB path, it is better to store the the relative path. OP can access the rest of the URL in the template if needed too and if the rest of the URL changes then OP only has to change in one place and not in the database(s).

How to add a function that creates a link to os.path.join(BASE_DIR, 'media/') in settings.py django?

I use froala editor to add text to the model and I want to change the folder where the images will be loaded from the form field.
My function to create a path looks like this:
#utilities.py
def article_img_directory_path(instance, filename):
article_title = slugify(instance.title, allow_unicode=True)
return 'images/{0}/{1}'.format(article_title, filename)
I don't know how to add this function to the editor's path correctly:
#settings.py
from articles.utilities import article_img_directory_path
FROALA_UPLOAD_PATH = os.path.join(BASE_DIR, 'media/')+str(article_img_directory_path)
Images are loaded and displayed, but as a result, the loading path is wrong
I ain't got the reputation to comment, but see are you using your models to save those files?
If yes,
use the upload_to attribute of FileField in your model and point it to article_img_directory_path, then automatically, all your files will be saved in your desired location.
If No,
I don't clearly get what you are trying to accomplish here, but
os.path.join(base_dir, 'media/') returns you the string path of the media folder.
You are trying to concatenate the bound method of your function here, not even invoking the function by using (). You gotta invoke the function by calling it and passing the arguments there. But I doubt that it will work from settings.py where you cannot access any instance.
So, I suggest you to look at the FileField and upload_to here https://docs.djangoproject.com/en/3.2/ref/models/fields/#:~:text=def%20user_directory_path(instance%2C%20filename)%3A%0A%20%20%20%20%23%20file%20will%20be%20uploaded%20to%20MEDIA_ROOT/user_%3Cid%3E/%3Cfilename%3E%0A%20%20%20%20return%20%27user_%7B0%7D/%7B1%7D%27.format(instance.user.id%2C%20filename)%0A%0Aclass%20MyModel(models.Model)%3A%0A%20%20%20%20upload%20%3D%20models.FileField(upload_to%3Duser_directory_path)

How to change the default media url for a in django file field?

I am using django-sendfile to protect certain files.
The problem is that when the file is displayed on the frontend it uses the MEDIA_ROOT location which is not where the file actually is.
The actual link (that checks permissions) that I want to use is:
http://127.0.0.1:8000/leave/supporting_doc/57
yet the link displayed is:
http://127.0.0.1:8000/media/leave/user_2/2018-09-06-logo.png
The field in the model is:
supporting_doc = models.FileField(
upload_to=user_leave_directory_path,
storage=SENDFILE_STORAGE,
blank=True,
validators=[FileExtensionValidator(ACCEPTED_FILE_TYPES)]
)
The upload to method give a link relative to MEDIA_ROOT:
def user_leave_directory_path(instance, filename):
'''Get the user directory for leave supporting document'''
# file will be uploaded to MEDIA_ROOT/user_<id>/<filename>
return 'leave/user_'\
f'{instance.user.id}/{instance.start_date}-{filename}'

Manually trigger image save method in Django model

I have a Django model with a customized image field. The image field creates some thumbnail sizes on upload. Code may look like this:
from django.db import models
from utils import CustomImageField
class Photo(models.Model):
image = CustomImageField()
Now I modify the original image, let's say I rotate it. And now I want to trigger the save method of my image field again, in order to overwrite the thumbnails and create rotated versions. So, I don't need to rotate the thumbnails elsewhere in my code (DRY).
Any thoughts? Something along those lines - but how exactly?
p = Photo.objects.get(pk=1)
p.image.save(...)
I have full control over the CustomImageField widget. The save() method is defined as:
def save(self, name, path, save=True):
Question is, what do I use for the methods parameters?
This question looks like a duplicate of Programmatically saving image to Django ImageField
The parameters of the ImageField.save() method are documented for FileField.save() (of which ImageField is a subclass):
https://docs.djangoproject.com/en/1.9/ref/models/fields/#django.db.models.fields.files.FieldFile.save
Takes two required arguments: name which is the name of the file, and
content which is an object containing the file’s contents. The
optional save argument controls whether or not the model instance is
saved after the file associated with this field has been altered.
Defaults to True.
Here is what is working for us:
class CustomImage(models.Model):
image = models.ImageField(upload_to=get_file_path, max_length=500)
orig_name = models.TextField()
This is the method that adds an image file to the ImageField from an http resource:
from django.core.files.base import ContentFile
def download_photo(amazon_id, url):
img_data = requests.get(url)
img = CustomImage(orig_name=img_data.url)
img.image.save(slugify(img.orig_name), ContentFile(img_data.content), save=True)
It also works without ContentFile:
new_img = File(open(different_obj.image.path), 'r')
img.image.save(different_obj.image.url, new_img, save=True)
See also:
- https://docs.djangoproject.com/en/1.9/topics/files/
- https://djangosnippets.org/snippets/2587/
An option is dirty field checking, either manually (see this SO question) or using a pypi package
Alternatively, if you want to conserve memory, the resizing can be triggered from the field's property setter (assuming you inherit from FileField
class CustomImageField(FileField):
def _set_file(self, file):
has_file_changed = file != self._file
super(CustomImageField, self)._set_file(file)
if has_file_changed:
self.handle_resizing_etc()
# need to redeclare property so it points to the right _set_file
file = property(FileField._get_file, _set_file, FileField._del_file)
disclaimer: I haven't used this approach in production code and I haven't written a proof of concept before posting this answer, so it might not work as desired

django custom file storage path

i would like to dynamically set the file storage path from the view regardless of the actual media_root path. is this possible. i have looked into custom storage objects and i am aware of the custom upload_to method call. currently i have a method that is called when my ImageField model upload_to is specified. this lets me change the directory within media_root. i have tried to do something similar with an overriden FileSystemStorage class but whatever it is set to i think it is bound before i can modify it within a view. if fileupload handler is the way to go i would be curious as to how to implement one.
If path that you specified in upload_to starts with / then it will be considered as absolute path. Through this you can set any path that you want regardless of MEDIA_ROOT.
you can do this in your view path = default_storage.save(filePath, ContentFile(file))
where filePath is file path where you need to store, and file is the file which is uploaded by user. this function will return you the path by storing file.
file = request.FILES['filee']
filePath = '%s/%s' % ('path/to/directory', file.name)
file = file.read()
path = default_storage.save(filePath, ContentFile(file))