0

I have followed multiple tutorials on how to use the DigitalOcean object storage known as DigitalOcean Spaces on my Django project but I'm not able to do it. Actually, I was using it before and it was working, after that I moved the static files to Contabo Object Storage, and apparently their CDN is pretty slow so when I decided to go back to DO, it does not work anymore, I even went to the commit where I had it working and copied the exact same code.

Here is the code I have on my settings.py:

from storages.backends.s3boto3 import S3Boto3Storage


class MediaStorage(S3Boto3Storage):
    bucket_name = "XXXX"


class StaticStorage(S3Boto3Storage):
    bucket_name = "XXXX"


DEFAULT_FILE_STORAGE = "nafssi.settings.MediaStorage"
STATICFILES_STORAGE = "nafssi.settings.StaticStorage"

AWS_ACCESS_KEY_ID = "XXXX"
AWS_SECRET_ACCESS_KEY = "XXX/XXXX/XXXXX"
AWS_S3_ENDPOINT_URL = "https://XXXX.fra1.digitaloceanspaces.com"
AWS_S3_OBJECT_PARAMETERS = {
    "CacheControl": "max-age=86400",
}

MEDIA_URL = f"{AWS_S3_ENDPOINT_URL}/media/"
STATIC_URL = f"{AWS_S3_ENDPOINT_URL}/static/"

When I try python manage.py collectstatic I have the following error:

You have requested to collect static files at the destination
location as specified in your settings.

This will overwrite existing files!
Are you sure you want to do this?

Type 'yes' to continue, or 'no' to cancel: yes
Traceback (most recent call last):
  File "D:\Data\Dropbox\D Drive\Toubib\Nafssi\Code\manage.py", line 22, in <module>
    main()
  File "D:\Data\Dropbox\D Drive\Toubib\Nafssi\Code\manage.py", line 18, in main
    execute_from_command_line(sys.argv)
  File "D:\Data\Dropbox\D Drive\Toubib\Nafssi\Code\nafssienv\lib\site-packages\django\core\management\__init__.py", line 442, in execute_from_command_line
    utility.execute()
  File "D:\Data\Dropbox\D Drive\Toubib\Nafssi\Code\nafssienv\lib\site-packages\django\core\management\__init__.py", line 436, in execute
    self.fetch_command(subcommand).run_from_argv(self.argv)
  File "D:\Data\Dropbox\D Drive\Toubib\Nafssi\Code\nafssienv\lib\site-packages\django\core\management\base.py", line 412, in run_from_argv
    self.execute(*args, **cmd_options)
  File "D:\Data\Dropbox\D Drive\Toubib\Nafssi\Code\nafssienv\lib\site-packages\django\core\management\base.py", line 458, in execute
    output = self.handle(*args, **options)
  File "D:\Data\Dropbox\D Drive\Toubib\Nafssi\Code\nafssienv\lib\site-packages\django\contrib\staticfiles\management\commands\collectstatic.py", line 209, in handle
    collected = self.collect()
  File "D:\Data\Dropbox\D Drive\Toubib\Nafssi\Code\nafssienv\lib\site-packages\django\contrib\staticfiles\management\commands\collectstatic.py", line 135, in collect
    handler(path, prefixed_path, storage)
  File "D:\Data\Dropbox\D Drive\Toubib\Nafssi\Code\nafssienv\lib\site-packages\django\contrib\staticfiles\management\commands\collectstatic.py", line 368, in copy_file
    if not self.delete_file(path, prefixed_path, source_storage):
  File "D:\Data\Dropbox\D Drive\Toubib\Nafssi\Code\nafssienv\lib\site-packages\django\contrib\staticfiles\management\commands\collectstatic.py", line 278, in delete_file
    if self.storage.exists(prefixed_path):
  File "D:\Data\Dropbox\D Drive\Toubib\Nafssi\Code\nafssienv\lib\site-packages\storages\backends\s3boto3.py", line 463, in exists
    self.connection.meta.client.head_object(Bucket=self.bucket_name, Key=name)
  File "D:\Data\Dropbox\D Drive\Toubib\Nafssi\Code\nafssienv\lib\site-packages\botocore\client.py", line 535, in _api_call
    return self._make_api_call(operation_name, kwargs)
  File "D:\Data\Dropbox\D Drive\Toubib\Nafssi\Code\nafssienv\lib\site-packages\botocore\client.py", line 980, in _make_api_call
    raise error_class(parsed_response, operation_name)
botocore.exceptions.ClientError: An error occurred (403) when calling the HeadObject operation: Forbidden

I even added some CORS permissions on DigitalOcean as follows:

enter image description here

  • It looks like there is a permission error trying to access your S3 bucket. Where do you run the command? Are you running this on your own computer or on a server somewhere? – Code-Apprentice Aug 08 '23 at 00:41
  • What command? It's a django web app. when you run collectstatic it's supposed to upload all static files to the bucket. I tried both on my local machine and remote server and same results – Kaïss Bouali Aug 08 '23 at 00:42
  • I mean where are you running `python manage.py collectstatic`? This only uploads yoru static files to the S3 bucket because you configured it to do so, but that isn't the default behavior. To solve your current problem, I suggest starting by checking your AWS credentials to make sure you have access to the bucket. – Code-Apprentice Aug 08 '23 at 01:34
  • Maybe try accessing the bucket with the same credentials but with the AWS CLI. – Code-Apprentice Aug 08 '23 at 01:35
  • As I said in my post, I'm using DigitalOcean, not AWS. – Kaïss Bouali Aug 08 '23 at 01:51
  • Well, I'm confused why you have a bunch of `AWS_*` settings and references to S3 and boto3, which are all AWS-related. – Code-Apprentice Aug 08 '23 at 04:05

1 Answers1

0

I found the solution, by tweaking the configuration, the changes were mainly in the endpoint URL and the media and static urls, also I added the Region Name for it to work.

Here is the updated code:

from storages.backends.s3boto3 import S3Boto3Storage


class MediaStorage(S3Boto3Storage):
    bucket_name = "XXXX"


class StaticStorage(S3Boto3Storage):
    bucket_name = "XXXX"


DEFAULT_FILE_STORAGE = "XXXX.settings.MediaStorage"
STATICFILES_STORAGE = "XXXX.settings.StaticStorage"

AWS_ACCESS_KEY_ID = config("AWS_ACCESS_KEY_ID")
AWS_SECRET_ACCESS_KEY = config("AWS_SECRET_ACCESS_KEY")


AWS_STORAGE_BUCKET_NAME = "XXXX"
AWS_S3_REGION_NAME = "fra1"
AWS_S3_ENDPOINT_URL = "https://fra1.digitaloceanspaces.com"


AWS_S3_OBJECT_PARAMETERS = {
    "CacheControl": "max-age=86400",
}

MEDIA_URL = "https://XXXX.fra1.digitaloceanspaces.com/media/"
STATIC_URL = "https://XXXX.fra1.digitaloceanspaces.com/static/"
  • It is probably the `AWS_S3_REGION_NAME` that fixed the problem. The changes to `MEDIA_URL` and `STATIC_URL` are superficial. The result of your original code using `f-strings` is identical to what you have here. – Code-Apprentice Aug 08 '23 at 03:55
  • No one more thing you missed, the S3_ENDPOINT_URL should not have had the XXX (name of the bucket) as a subdomain to fra1.xxxxx so 2 changes made the solution – Kaïss Bouali Aug 08 '23 at 13:52
  • You already had the bucket name in your original code with `AWS_S3_ENDPOINT_URL = "https://XXXX.fra1.digitaloceanspaces.com"`. – Code-Apprentice Aug 08 '23 at 14:51