Django uploading images - python

I want to upload images in the django admin interface. During development everything works fine but when I put the files on my server it doesn't work.
I have two different paths on my Server. One where I put all my source files and one where I put all the static files.
Path for source files: /htdocs/files/project/
Path for static files: /htdocs/html/project/
If I upload an image, then it is saved in /htdocs/files/project/media/. But I want to save it in /htdocs/html/project/. How can I change the path?
Here are my settings:
STATIC_URL = '/static/'
MEDIA_URL = '/media/'
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
STATICFILES_DIRS = (
os.path.join(BASE_DIR, 'static'),
'/var/www/ssd1257/htdocs/html/'
)
And here is my model:
class News(models.Model):
title = models.CharField(max_length=200, null=False)
date = models.DateField(null=False, default=datetime.now)
text = models.TextField(null=False, blank=True)
image = models.ImageField(upload_to="./news/")

The uploaded files are saved normally in the following path
MEDIA_URL + the path specified in “upload_to” attribute in the model class
So in your case,
MEDIA_ROOT = os.path.join(BASE_DIR, 'media') = “/htdocs/files/project/media”
Django will create the path if it doesn’t exits
But I didn’t get the dot in-frontront of ‘upload_to’ to path(“./news/“)
So if you want to change the path where uploaded files are stored, simply change the MEDIA_ROOT
Note, please provide the absolute full path
I guess it will be
MEDIA_ROOT = '/var/www/ssd1257/htdocs/html/project'
Also, its better to rename the uploaded files before saving to avoid file_name conflicts
def get_news_image_path(instance, filename):
path_first_component = ‘news/‘
ext = filename.split('.')[-1]
timestamp = millis = int(round(time.time() * 1000))
file_name = ‘news_’ + str(instance.id) + str('_logo_image_') + timestamp + str('.') + ext
full_path = path_first_component + file_name
return full_path
class News(models.Model):
title = models.CharField(max_length=200, null=False)
date = models.DateField(null=False, default=datetime.now)
text = models.TextField(null=False, blank=True)
image = models.ImageField(upload_to=get_news_image_path)
Now the uploaded files will be saved in
'/var/www/ssd1257/htdocs/html/project/news’
You are Done
In addition, also set appropriate MEDIA_URL
Ex: MEDIA_URL = “media
So when generated URL for the upload images will be
MEDIA_URL + upload_to path
Also, configure the web server to serve these URLs from appropriate locations

from django.core.files.storage import FileSystemStorage
upload_storage = FileSystemStorage(location=UPLOAD_ROOT, base_url='/') #upload root set to your project directory
class News(models.Model):
title = models.CharField(max_length=200, null=False)
date = models.DateField(null=False, default=datetime.now)
text = models.TextField(null=False, blank=True)
image = models.ImageField(upload_to='/', storage=upload_storage)

Self-inflicted by this setting:
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
Change that to:
MEDIA_ROOT = '/htdocs/html/project/'

Related

Selenium screenshots are not saved on docker (Python)

Code sequence
self.driver.save_screenshot('./logs/{}.png'.format(step.id))
log = Logs(step=step, attachment='./logs/{}.png'.format(step.id), aditional_data={},
flow_instance=self.flowinstance)
log.save()
The picture is not saved at all in the Docker web container and cannot be accessed through the log.
error given
Logs model
class Logs(models.Model):
step = models.ForeignKey(Step, on_delete=models.CASCADE)
attachment = models.ImageField(upload_to='logs/', blank=True)
aditional_data = models.JSONField()
flow_instance = models.ForeignKey(FlowInstance, on_delete=models.CASCADE)
settings.py
BASE_DIR = os.path.dirname(os.path.dirname(__file__))
MEDIA_ROOT = os.path.join(BASE_DIR, 'media').replace('\\', '/')
MEDIA_URL = '/media/'
urls.py i added
+ static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
In docker-compose I have selenium-hub, browser instance, worker / beat. All this works correctly, the only problem is when the picture should be taken and saved, which does not happen.

FileNotFoundError at /user/profile/edit [Errno 2] No such file or directory: 'user_3/profile.jpg'

I`m beginner of django and try to make small newsfeed like instagram.
And I have issue, after I connect the backend storage to S3 for media and staticfiles, my media file has some problem.
I have error "FileNotFoundError at /user/profile/edit [Errno 2] No such file or directory" or "This backend doesn't support absolute paths." or "Key error 'JPG'".
I have searched about this problem, and there is something about file format between S3 and pillow is different. But when I try to save pic.save(self.picture.name) or pic.save(self.picture.path), then I have key error about image format.
But it upload to S3 properly, just python can not find it.
I have no idea which part is wrong.
Can someone please tell me?
model.py
def user_directory_path_profile(instance, filename):
# file will be uploaded to MEDIA_ROOT/user_<id>/<filename>
profile_pic_name = 'user_{0}/profile.jpg'.format(instance.user.id)
full_path = os.path.join(settings.MEDIA_ROOT, profile_pic_name)
if os.path.exists(full_path):
os.remove(full_path)
return profile_pic_name
def user_directory_path_banner(instance, filename):
# file will be uploaded to MEDIA_ROOT/user_<id>/<filename>
banner_pic_name = 'user_{0}/banner.jpg'.format(instance.user.id)
full_path = os.path.join(settings.MEDIA_ROOT, banner_pic_name)
if os.path.exists(full_path):
os.remove(full_path)
return banner_pic_name
class Profile(models.Model):
user = models.OneToOneField(
User, on_delete=models.CASCADE, related_name='profile')
location = models.CharField(max_length=50, null=True, blank=True)
url = models.CharField(max_length=80, null=True, blank=True)
profile_info = models.TextField(max_length=150, null=True, blank=True)
created = models.DateField(auto_now_add=True)
picture = models.ImageField(
upload_to=user_directory_path_profile, blank=True, null=True, verbose_name='Picture')
banner = models.ImageField(
upload_to=user_directory_path_banner, blank=True, null=True, verbose_name='Banner')
def save(self, *args, **kwargs):
super().save(*args, **kwargs)
SIZE = 250, 250
if self.picture:
pic = Image.open(self.picture)
pic.thumbnail(SIZE, Image.LANCZOS)
pic.save(self.picture.name)
settings.py
BASE_DIR = Path(__file__).resolve().parent.parent
ROOT_DIR = os.path.dirname(BASE_DIR)
STATIC_URL = '/static/'
STATIC_ROOT = os.path.join(ROOT_DIR, 'static')
STATICFILES_DIRS = [
os.path.join(BASE_DIR, 'djfans/static'),
]
STATICFILES_STORAGE = 'storages.backends.s3boto3.S3StaticStorage'
MEDIA_URL = '/media/'
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
DEFAULT_FILE_STORAGE = 'storages.backends.s3boto3.S3Boto3Storage'
I searched some answers like a similar problem, and things were like
image.save(name)
or
storage_path = storage.open(photo.img.name, "wb")
resized_image.save(storage_path, 'png')
storage_path.close()
something like this, but it`s not working(or I did something wrong again).
Mega thanks for your help.

Django upload FileField and ImageField in differnt servers

I want to make a system where user can upload document files and also images (both for different tasks)
and i want to store the files in my own ftp server and images in s3 bucket.
i am using django-storages package
never saw a django approach like this, where FileField and ImageFields can be uploaded to different servers
for example, let's say when user uploads a file the file gets uploaded to my ftp server
FTP_USER = 'testuser'#os.environ['FTP_USER']
FTP_PASS = 'testpassword'#os.environ['FTP_PASS']
FTP_PORT = '21'#os.environ['FTP_PORT']
DEFAULT_FILE_STORAGE = 'storages.backends.ftp.FTPStorage'
FTP_STORAGE_LOCATION = 'ftp://' + FTP_USER + ':' + FTP_PASS + '#192.168.0.200:' + FTP_PORT
# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/1.11/howto/static-files/
STATIC_URL = '/static/'
STATICFILES_DIRS = [
os.path.join(BASE_DIR, "static_my_proj"),
]
STATIC_ROOT = os.path.join(BASE_DIR, "static_cdn", "static_root")
MEDIA_URL = 'ftp://192.168.0.200/'
MEDIA_ROOT = 'ftp://192.168.0.200/'#os.path.join(BASE_DIR, "static_cdn", "media_root")
but problem is images now goto ftp server also
because of this
DEFAULT_FILE_STORAGE = 'storages.backends.ftp.FTPStorage'
yeah i know i can make different directories inside uploaded server root directory like this
def get_filename_ext(filepath):
base_name = os.path.basename(filepath)
name, ext = os.path.splitext(base_name)
return name, ext
def upload_image_path(instance, filename):
# print(instance)
#print(filename)
new_filename = random.randint(1,3910209312)
name, ext = get_filename_ext(filename)
final_filename = '{new_filename}{ext}'.format(new_filename=new_filename, ext=ext)
return "myapp/{new_filename}/{final_filename}".format(
new_filename=new_filename,
final_filename=final_filename
)
class Product(models.Model):
title = models.CharField(max_length=120)
slug = models.SlugField(blank=True, unique=True)
document = models.FileField(upload_to=upload_image_path, null=True, blank=True)
def get_absolute_url(self):
#return "/products/{slug}/".format(slug=self.slug)
return reverse("detail", kwargs={"slug": self.slug})
def __str__(self):
return self.title
but that's not what i want, i want different servers for file and image uploads
is that even possible ? i mean there can be only one MEDIA_ROOT so how can i write two server addresses, am i making sense ?
EDIT 1:
iain shelvington mentioned a great point, that to add storage option for each field for customized storage backend
like this
from storages.backends.ftp import FTPStorage
fs = FTPStorage()
class FTPTest(models.Model):
file = models.FileField(upload_to='srv/ftp/', storage=fs)
class Document(models.Model):
docfile = models.FileField(upload_to='documents')
and in settings this
DEFAULT_FILE_STORAGE = 'storages.backends.ftp.FTPStorage'
FTP_STORAGE_LOCATION = 'ftp://user:password#localhost:21
but user uploaded photos also gets uploaded to that ftp server
due tp
DEFAULT_FILE_STORAGE = 'storages.backends.ftp.FTPStorage'
and about the MEDIA_URL and MEDIA_ROOT they can be only one right ?
so how can i put two different server address there ?
Thanks for reading this, i really appreciate it.
You can set a base_url in the FTPStorage class as
from storages.backends.ftp import FTPStorage
from django.conf import settings
fs = FTPStorage(base_url=settings.FTP_STORAGE_LOCATION)
class FTPTest(models.Model):
file = models.FileField(upload_to='srv/ftp/', storage=fs)
class Document(models.Model):
docfile = models.FileField(upload_to='documents')
This base_url is useful in building the "absolute URL" of the file and hence you don't need MEDIA_URL and MEDIA_ROOT "in this case"
I want different servers for file and image uploads.
You can achieve it by specifying the storage parameter the FileField (or ImageField)
but user uploaded photos also gets uploaded to that ftp server due to, DEFAULT_FILE_STORAGE settings.
It is your choice. What should be the default storage class in your case? Do you need to upload the media files to S3? or local storage, where the project runs? set the value accordingly.

How to combine django-ckeditor upload path with ImageField upload path

Model:
content = RichTextUploadingField(blank=True, null=True)
image = models.ImageField(upload_to="news/%Y/%m")
I set this in settings.py
MEDIA_URL = '/media/'
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
CKEDITOR_UPLOAD_PATH = 'news/%Y/%m'
But the images still go to different folders.Is there anyway to make two paths one?
Best regards!

why does file.url returns the same value as file.path in django?

I'm in the middle of a very strange issue here.
I have a FileField with a default value in a model declared as follow:
class MyModel(models.Model):
name = models.CharField(max_length=32)
audio_file = models.FileField(upload_to='user_menus/', default='%suser_menus/default.mp3' % settings.MEDIA_ROOT, blank=True, null=False)
Now, when I do the following
>>> a = MyModel(name='Foo')
>>> a.save()
>>> a.audio_file.path
'/full/path/to/file'
>>> a.audio_file.url
'/full/path/to/file' # again
I have my MEDIA_ROOT and MEDIA_URL configured as follows
MEDIA_ROOT = os.path.join(os.path.dirname(__file__), 'static/')
MEDIA_URL = '/media/'
Am i missing something?
any advice?
Thank you in advance.
You need to specify in the default value of the field the actual value (string) you want to save in the database, not the full path. That's why the .url is showing up that way. For your case should be like this:
audio_file = models.FileField(upload_to='user_menus/', default='%suser_menus/default.mp3' % settings.MEDIA_URL, blank=True, null=False)
Notice that I just think you'll having this problem when the default is inserted in the database.
Hope this helps!
There are a couple of things I don't think you need, which may or may not be causing the problem. I have the following code working perfectly in production (Django 1.5). models.py:
...
decision_file = models.FileField(
upload_to = "guidance",
blank = True,
help_text = "20MB maximum file size."
)
...
And in my base settings.py:
MEDIA_ROOT = os.path.join(os.path.dirname(__file__), '../../media')
MEDIA_URL = '/media/'
STATIC_ROOT = os.path.join(os.path.dirname(__file__), '../../static/')
STATIC_URL = '/static/'
Notice I'm defining separate paths and urls for static and media files. I don't think you should include the format string with % settings.MEDIA_ROOT in your default (see Paulo Bu's answer) or use the trailing slash in the upload_to parameter.
In summary
check the upload folder exists;
set separate static and media paths and urls;
remove the format string from your defaul; and
remove the trailing slash from the upload_to parameter
and you should have working code.

Categories