I am trying to write a custom template loader in django which serves html templates which are present in a folder in my s3 bucket. Following is my custom_loader file
from django.conf import settings
from django.template import Origin, Engine
from django.template.loader import TemplateDoesNotExist
from django.template.loaders.base import Loader
from boto3.session import Session
from django.template import engines
ACCESS_KEY_NAME = getattr(settings, 'AWS_ACCESS_KEY_ID', getattr(settings, 'AWS_ACCESS_KEY_ID', None))
SECRET_KEY_NAME = getattr(settings, 'AWS_SECRET_ACCESS_KEY', getattr(settings, 'AWS_SECRET_ACCESS_KEY', None))
TEMPLATE_BUCKET = getattr(settings, 'AWS_STORAGE_BUCKET_NAME')
django_engine = engines['django']
template = django_engine.from_string("Hello {{ name }}!")
class S3Engine(Engine):
def __unicode__(self):
return "s3_engine"
def __str__(self):
return "s3_engine"
class Loader(Loader):
is_usable = True
def __unicode__(self):
return "loader"
def __init__(self, *args, **kwargs):
django_engine = engines['django']
print(engines.all())
template = django_engine.from_string("Hello {{ name }}!")
print(template)
params = args[0]
print(args)
print('params', params)
session = Session(aws_access_key_id=ACCESS_KEY_NAME,
aws_secret_access_key=SECRET_KEY_NAME)
s3 = session.resource('s3')
self.bucket = s3.Bucket(TEMPLATE_BUCKET)
super(Loader, self).__init__(*args, **kwargs)
# self.engine = S3Engine(dirs=params['DIRS'], context_processors=options, loaders=Loader)
def getKeys(self):
keys_objects = []
for obj in self.bucket.objects.filter(Prefix="media/festive_html/"):
key = obj.key
keys_objects.append({
'key': key,
'object': obj
})
return keys_objects
def get_contents(self, origin):
print(111111)
print('origin', origin)
try:
keys_objects = self.getKeys()
for key_object in keys_objects:
print('origin', origin)
print('key_object', key_object)
if key_object['key'] == origin:
return key_object['object'].get()['Body'].read()
except FileNotFoundError:
raise TemplateDoesNotExist(origin)
def get_template_sources(self, template_name, template_dirs=None):
tried = []
# print('template_name', template_name)
# template_name = "media/" + template_name
print(11111)
yield Origin(
name=template_name,
template_name=template_name,
loader=self,
)
print(333333)
tried.append('/index.html')
print(444444)
if tried:
print(555555555)
error_msg = "Tried Keys %s" % tried
else:
print(6666666)
error_msg = "Your TEMPLATE_DIRS setting is empty. Change it to point to at least one template directory."
raise TemplateDoesNotExist(error_msg)
get_template_sources.is_usable = True
and in my settings i have set the template settings in following way.
TEMPLATES = [
{
'NAME': 'django',
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [os.path.join(BASE_DIR, 'templates'), os.path.join(BASE_DIR, 'media')],
'APP_DIRS': False,
'OPTIONS': {
'loaders': [
'django.template.loaders.filesystem.Loader',
'django.template.loaders.app_directories.Loader',
's3template_loader.Loader',
],
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
],
},
},
]
and following is my view
def generate_html(request, template_id)
template_instance = TemplateData.objects.get(id=template_id)
html = template_instance.html
rendered = render_to_string(html, response)
return rendered
but when i am trying to access my end point i am getting the below error:
TypeError: 'Engine' object has no attribute '__getitem__'
PS: This question is similar to the below question with the difference that I don't want to use a different template Engine but just a different template loader that renders templates from s3.