DEV Community

Will Meyers
Will Meyers

Posted on

Storing Media Files on Bunny.net with Django

Bunny.net is a fast and reliable CDN. I'm going to show you how to set up and start using Bunny.net in your next Django project.

Bunny.net Setup

Go to bunny.net and login. Click on the Storage icon and then on Add Storage Zone. Give your storage zone a name and select the geolocations that best fit your need. In this guide I'll call my zone myzone in location New York.

Once created you'll be redirected to the File Manager for your zone. Click on the Connect Pull Zone button in the top right. Again, give it a name (I like to keep names of my zones consistent) and select that options that best fit your CDN needs.

Django Setup

We assume that you've already created and done a the bare minimum of setting up a new django project.

We'll first edit our settings.py and include some new attributes. In bunny.net, under Storage, click FTP & API Access. Copy the Username and Password found on the page and save them as attributes in your settings.

I also went ahead and set the default file storage to a BunnyStorage class (that we'll create below) and changed the media url to that of the respective pull zone we created.

# Media files
#

DEFAULT_FILE_STORAGE = 'myapp.storage.BunnyStorage'

MEDIA_URL = 'https://myzone.b-cdn.net/myzone/media/'


# Bunny.net CDN Access
#

BUNNY_ZONENAME = 'myzone'

BUNNY_PASSWORD = 'arandom-string-of-numbersand-letters'
Enter fullscreen mode Exit fullscreen mode

As of Feb. 2021, Bunny.net does not have an official Python API. However, they do link NiveditJain's library as a stable library. It's just a single file so we'll just wget it into our django project folder (where manage.py is saved) and import it relatively to our custom storage module.

cd myproject

wget https://raw.githubusercontent.com/NiveditJain/BunnyCDNStorageLib/master/BunnyCDNStorage.py
Enter fullscreen mode Exit fullscreen mode

Important!

You must edit the BunnyCDNStorage.py file before proceeding! Change the upload_file method to the one below.

def upload_file(self,cdn_path,file_name,file_data):
        """
            uploads your files to cdn server \n
            cdn_path - directory to save in CDN \n
            filename - name to save with cdn \n
            if none it will look for file in present working directory
        """

        if(cdn_path[-1]=='/'):
            cdn_path=cdn_path[:-1]

        request_url=self.base_url+cdn_path+'/'+file_name

        response=requests.request("PUT",request_url,data=file_data,headers=self.headers)

        return(response.json())
Enter fullscreen mode Exit fullscreen mode

Once done, change directory into the django app you'd like to associate the storage backend to and create a new file storage.py.

The django docs provide in-depth documentation of writing custom storage backends. So, if you want to get a deeper understanding of what we're doing exactly, you should check those pages out.

Our storage backend consists of a single class and five methods.

In myapp/storage.py,

from django.conf import settings
from django.core.files.images import ImageFile
from django.core.files.storage import Storage

import BunnyCDNStorage


class BunnyStorage(Storage):
    def __init__(self):
        self.conn = BunnyCDNStorage.CDNConnector(
            settings.BUNNY_PASSWORD,
            settings.BUNNY_ZONENAME,
            storage_zone_region='ny'
        )

    def _open(self, name, mode='rb'):
        f = self.conn.get_file(name)

        return ImageFile(f)

    def _save(self, name, content):
        self.conn.upload_file('/media/', name, content)

        return name

    def delete(self, name):
        self.conn.remove(name)

    def exists(self, name):
        try:
            self.conn.get_file(name)
        except ValueError:
            return False

        return True

    def listdir(self, path):
        pass

    def size(self, name):
        pass

    def url(self, name):
        return f'https://myzone.b-cdn.net/media/{name}'

Enter fullscreen mode Exit fullscreen mode

And that's it! Until Bunny.net releases an official Python API and a standard Django package is released, this is kind of the best we got right now... Happy coding!

Top comments (2)

Collapse
 
armen1337 profile image
Armen

Hi, thanks for very valuable and useful post! All works fine for me except for uploading new files from admin panel. Maybe I should make connection to bunny storages in settings file in some way?

Collapse
 
willmeyers profile image
Will Meyers

Hi Armen, I'm incredibly sorry about getting back to you so late. A lot has changed in my life since publishing this (new job, moving... etc). I've since written a library (github.com/willmeyers/django-bunny...) that is much more stable than this. If you're still having issues feel free to raise an issue and we can take a closer look at what's going on. Thanks for commenting and again so sorry for the very late reply!