Django upload FileField and ImageField in differnt servers

Viewed 766

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.

1 Answers

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