Django upload FileField and ImageField in differnt servers - python

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.

Related

Upload files from django to a specific directory in a server?

I have a django-admin panel and a Windows Virtual Private Server.
What i want to do is upload files from django admin panel to a directory like this :
C:\site\media
and i dont want to upload files to django app folder .
This is my settings.py file :
STATIC_ROOT = os.path.join(BASE_DIR,'static')
STATIC_URL = '/static/'
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
MEDIA_URL = '/media/'
if not os.path.exists(MEDIA_ROOT):
os.makedirs(MEDIA_ROOT)
and This is my model :
class Pictures(models.Model):
product = models.ForeignKey('Products', models.DO_NOTHING)
picurl = models.ImageField()
def __unicode__(self):
return self.title
class Meta:
managed = False
db_table = 'pictures'
verbose_name_plural = "ProductPicturess"
def __str__(self):
return '%s------- (%s)' % (self.product.title,self.picurl)
How should i change it's values ?
Thank you .
After Searching alot and triying different values finally i found the solutin .
Simply I changed MEDIA_ROOT to this :
MEDIA_ROOT = os.path.join(BASE_DIR, '../../../realwamp/wamp64/www/myproject/pictures/')
And volla , My Problem is solved .
With three pairs of dots like ../../../ I back to the C:\ directory and then go to my www folder .

Django uploading images

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/'

Django Rest app not using media root correctly to serve images

I have a project that has 3 apps, one named stores with store models, products with product models, and api which is the rest framework app that serves the Json results to clients. I set the media root in settings.py as MEDIA_ROOT = '/photos/' and the upload works for both product and store models. The main problem here is that for some reason the rest framework returns a url that references the api app instead of the products or stores apps for the media root url. here are my models
class Product(models.Model):
def get_image_path(instance, filename):
return '/Products/' + filename
picture = models.ImageField(width_field=None, max_length=100, blank =True, null =True)
store:
class Store(models.Model):
def __str__(self):
return self.name
def get_image_path(instance, filename):
return os.path.join('productphotos', 'stores', filename)
picture = models.ImageField(width_field=None, max_length=100, blank =True, null =True)
How do i set the mediaroot to the project directory instead so that all apps in the project reference it as mediaroot instead of themselves?
The upload works and upoads the pictures to the instructed directories in the root of the project (where manage.py is found), but the rest framework thinks it should get the media from the api app.. what's the proper way of doing this? here are screenshots:
the path uploaded to
the path returned in json
The MEDIA_URL setting is the URL path in the browser. The MEDIA_ROOT setting is the root directory on your server, and should be an absolute path.
MEDIA_URL = '/pictures/'
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
MEDIA_ROOT = os.path.join(BASE_DIR, 'uploaded_pictures')
Also, if you want Product and Store pictures to go into different sub directories, for example pictures/products/ and pictures/store/, you'd need to set the upload_to argument on the model field. For example
picture = models.ImageField(upload_to='products/', ... )
Edit: To serve static and media files during development, add this at the end of the urls.py
if settings.DEBUG:
from django.contrib.staticfiles.urls import staticfiles_urlpatterns
from django.conf.urls.static import static
urlpatterns += staticfiles_urlpatterns()
urlpatterns += static(
settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)

Upload to S3 from Django admin

I've got my django app setup to use S3 using storages and boto. Using collectstatic, I was able to move my static assets to S3. However, I need to also store the image files uploaded from Django Admin to S3.
I used the django-s3direct package from here. I was able to set it up correctly and the upload seems to work. However, on loading the template, the uploaded image is not served.
My Settings.py:
STATICFILES_STORAGE = 'storages.backends.s3boto.S3BotoStorage'
AWS_ACCESS_KEY_ID = 'ACCESS_KEY'
AWS_SECRET_ACCESS_KEY = 'SECRET_KEY'
AWS_STORAGE_BUCKET_NAME = 'bucketname'
S3DIRECT_ENDPOINT = 's3.amazonaws.com' # http://docs.aws.amazon.com/general/latest/gr/rande.html#s3_region
S3DIRECT_DIR = 's3direct' # (optional, default is 's3direct', location within the bucket to upload files)
S3DIRECT_UNIQUE_RENAME = False # (optional, default is 'False', gives the uploaded file a unique filename)
Models.py:
class BannerAds(models.Model):
id = models.AutoField(primary_key=True)
name = models.CharField(max_length=255)
phone = models.BigIntegerField(max_length=20)
image = S3DirectField(upload_to='s3direct')
What you need to do is set up media files, which include uploades.
There are several ways to do this, I used django-storages
Among other things, you have to change your urls.py:
urlpatterns = [
...
] + + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
and yes you have to add a setting for MEDIA_ROOT as well.
But the big thing is media files, google that and you'll be on your way.

Django - serving user uploaded images

I am having some problems with serving user uploaded files from my Django application:
from models.py:
class Picture (models.Model):
title = models.CharField(max_length=48)
date_added = models.DateTimeField(auto_now=True)
content = models.ImageField(upload_to='pictures')
From the Django admin the files get uploaded to the user_res/pictures/ folder.
from the project's settings.py:
MEDIA_ROOT = 'user_res'
MEDIA_URL = '/user_res/'
STATIC_ROOT = ''
STATIC_URL = '/static/'
Every time I try to reference a static resource (namely css or js files), everything works fine using URLs such as
http://localhost:8000/static/<subfolder>/main.css.
However, I cannot access user uploaded files (which get created by the admin interface in the user_res/pictures folder with a relative URL such as
user_res/pictures/test.jpg
the URL is dynamically created with this line of code from a Django Picture model callable:
return '<img src="{}"/>'.format(self.content.url)
I have no dedicated url-s for either static or media files in the url.py file.
Does anybody have any idea as to how to make Django serve the media files? I understand that for live environments I will need to configure an http server to serve that particular directory, but for now I want to maintain a lightweight development suite.
Thank you.
Edit your urls.py file as shown below.
from django.conf import settings
from django.conf.urls.static import static
urlpatterns = patterns('',
# ... the rest of your URLconf goes here ...
) + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
edit your projects settings.py to look like:
#Rest of the settings
MEDIA_URL = '/media/'
MEDIA_ROOT = 'media'
STATIC_ROOT = ''
STATIC_URL = '/static/'
Please read the official Django documentation about serving files uploaded by a user carefully. Link to docs: https://docs.djangoproject.com/en/1.5/howto/static-files/#serving-files-uploaded-by-a-user
I think the url attribute returns a relative URL ( Django's FileField documentation ), so you should have:
return '<img src="{}"/>'.format(MEDIA_URL + self.content.url)
Relative URLs won't work, as a user visiting "http://localhost/books/" would be requesting "http://localhost/books/user_res/pictures/test.jpg".

Categories