How do I reset template loader cache in Django 1.9? - django

I used to be able to import django.template.loader.template_source_loaders and call reset() on all loaders to reset all template loader cache, but this no longer works.
How do I reset template loader cache in Django 1.9?
My settings, just in case this is useful:
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [os.path.join(BASE_DIR, 'accounts/templates')],
'APP_DIRS': True
}
]
This is how I load my template:
from django.template import TemplateDoesNotExist
from django.template.loader import get_template
from django.template.response import TemplateResponse
from django.http import HttpResponse
from django.views.decorators.cache import never_cache
from django.views.decorators.csrf import ensure_csrf_cookie
#never_cache
#ensure_csrf_cookie
def view(request, **kwargs):
try:
template = get_template('index.html')
except TemplateDoesNotExist:
return HttpResponse("Run `make template`")
return TemplateResponse(request, template)
I'm experiencing this issue on local dev using the built-in runserver, with DEBUG=True. The issue does not apply on production because the template will always exist.

Django does not cache the templates, but it does cache the list of app template directories used by the app directories loader. If you create a new directory e.g. polls/templates after starting the server, then Django will not pick up templates in this directory until the server has been restarted.

Really easy:
from django.template.utils import get_app_template_dirs
get_app_template_dirs.cache_clear()

Related

Is there any way to change the default path which Django will use to locate files in generic class based views?

So I am making a Blog website. I am using Class Bases Views to give the users an ability to add posts, view posts, update and delete them. So in my views.py, I have this:
from django.shortcuts import render, HttpResponse
from .models import Post
from django.views.generic import ListView, DetailView
# Create your views here.
def home(request):
context = {
'posts': Post.objects.all()
}
return render(request, 'index.html', context)
class PostListView(ListView):
model = Post
template_name = 'index.html'
context_object_name = 'posts'
ordering = ['-date_posted']
class PostDetailView(DetailView):
model = Post
My urls.py:
from django.urls import path
from . import views
from .views import PostListView, PostDetailView
urlpatterns = [
path('', PostListView.as_view(), name="home"),
path('post/<int:pk>/', PostDetailView.as_view(), name="post-detail"),
]
The problem is in the PostDetailView. When I create a file called post_detail.html in my templates folder, so that when user goes to a specific post in the website, we redirect them to the post_detail.html. But the site says that post_detail.html template cannot be found.
I have learnt that the the generic class based views will be looking for a template with this naming convention, <app>/<module>_<viewtype>.html. So it's going to be looking in the directory of the app name, which, in my case, is going to be "blog_app" then a template with a model name which is going to be "Post" and then the view type.
Is there any way to change the default path which Django will use to locate files in generic class based views?
So that I can then tell Django to look in my templates folder to search for post_detail.html template.
Note: I have registered my templates folder in the settings.py in the "dirs" like this 'DIRS': ['templates'],
Thanks
If you need to register your project’s templates directory folder then the setting that needs to be modified is DIRS inside TEMPLATES.
'DIRS': [os.path.join(BASE_DIR, 'templates')]
The BASE_DIR will already exist if you created your project using the default project template.
If APP_DIRS option is set to True in TEMPLATES, then
this is the relative path where your post_detail.html should be present.
blog_app/templates/blog_app/post_detail.html

ImportError: cannot import name 'views' from '__main__' in django

I made a simple web app but I got this:
My urls.py file:
from django.urls import path
from . import views
urlpatterns=[
path('',views.home,name='home')
(test) C:\Users\abc\projects\amar>C:/Users/abc/envs/test/Scripts/python.exe c:/Users/abc/projects/amar/f1/urls.py
Traceback (most recent call last):
File "c:/Users/abc/projects/amar/f1/urls.py", line 3, in <module>
from . import views
ImportError: cannot import name 'views' from '__main__'
(c:/Users/abc/projects/amar/f1/urls.py)
In views.py :
from django.shortcuts import render
def home(request):
return render(request,'home.html')
And in settings.py template, I also mention path:
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [os.path.join(BASE_DIR,'templates')],
You're not supposed to run urls.py directly. That won't work at all.
Start the server by running manage.py runserver.

How to add Django statements to Javascript

I'm trying to implement some JS code in django so anytime i click a button, it returns the current year.. how do i do this
I've tried using some JS events handler in my django based templates
from datetime import datetime
from django.template import Template, Context
from django.http import HttpResponse as toHTML
cont = Context({'dat':datetime.now()})
def say_year(request):
htm = Template("<button onclick='alert({dat})'>click me</button>")
htm = htm.render(cont)
return toHTML(htm)
i'm expecting an alert box showing full datetime.now() methods
I prefer that you do it that way in order to have full control over the template.
1 - make the views.py that way :
from datetime import datetime
from django.template import Template, Context
from django.shortcuts import render
def say_year(request):
context = {
'dat': datetime.now()
}
return render(request, 'mytemplate.html', context)
2- The urls.py should look that way :
from django.contrib import admin
from django.urls import path
from your_app import views
urlpatterns = [
path('admin/', admin.site.urls),
path('my_template/', views.say_year )
]
3- You create a templates folder in the root directory of your project where all your templates will live.
For your question i have create my_template.html and it should be that way :
<button onclick="alert('{{dat}}')">click me</button>
If you have more questions please let me know.

How do I disable Django per-view caching when debug is on?

I've written a bunch of views in Django that use per-page caching. The code looks like this:
from django.http import HttpResponse
from django.views.decorators.cache import cache_page
#cache_page(60 * 5)
def view_page(request):
return HttpResponse('hello world')
This works wonderfully, but is a pain during testing. How do I only do caching with debug off?
Check out django's dummy cache backend.
So for your development enviroment you should set your cache backend to django.core.cache.backends.dummy.DummyCache
You could conditionally decorate your view.
from django.http import HttpResponse
from django.views.decorators.cache import cache_page
from django.conf import settings
def view_page(request):
return HttpResponse('hello world')
if not settings.DEBUG:
view_page = cache_page(60 * 5)(view_page)
or perhaps this would work.
from django.http import HttpResponse
from django.views.decorators.cache import cache_page, never_cache
from django.conf import settings
production_cache = lambda func: cache_page(60 * 5)(func) if settings.DEBUG else never_cache(func)
#production_cache
def view_page(request):
return HttpResponse('hello world')
In fact it can be done without a lambda
from django.http import HttpResponse
from django.views.decorators.cache import cache_page, never_cache
from django.conf import settings
production_cache = cache_page(60 * 5) if not settings.DEBUG else never_cache
#production_cache
def view_page(request):
return HttpResponse('hello world')
Using #StephenPaulger's method, it will also prevent Django from setting the cache related headers like Expires. If you're working with another system that interprets these headers and keeps it's own cache as long as the date in the Expires header isn't reached, this can be pretty annoying while developing.
If you use never_cache, Django will set the Expires header to the current time of the request, so the document would be outdated right away.
You can create this in a separate file in your project:
from django.conf import settings
from django.views.decorators.cache import (
cache_page as django_cache_page, never_cache
)
if settings.DEBUG:
cache_func = lambda seconds: never_cache
else:
cache_func = django_cache_page
def cache_page(seconds):
return cache_func(seconds)
Then you can import this custom cache_page function instead of the native Django one and use it the same way. This if statement would only be executed once when the module is imported.
If you have separate settings files (for development and production) you can even make it more efficient by putting the functions in the settings files. So for the development settings you would do this:
from django.views.decorators.cache import never_cache
CACHE_FUNC = lambda seconds: never_cache
And in the production settings you would put:
from django.views.decorators.cache import cache_page
CACHE_FUNC = cache_page
Then in a separate file in your project:
from django.conf import settings
def cache_page(seconds):
return settings.CACHE_FUNC(seconds)
With this method, the CACHE_FUNC would be defined only once during the startup of Django. So no impact on performance, and no annoying Expires headers during development!

Django integration with Mako Jinja2 template comparison using : render_to_response. Problem?

I am using Django to build up my web project. As known that mako and Jinja2 template are faster that the one Django's given, I start finding way to integrate mako and Jinja2 into Django with using the Django's way of render_to_response method. After a lot research, I finally figure out the way to make this happen. However, in my integration, the jmeter's performance is something like Jinja2 (3ms) > Django's template (50ms) > mako (218ms).
If I went wrong with something?....Or pls help to advise some best practice to integrate jinja2 and mako.
Below is the coding ()
Mako2django.py
from django.http import HttpResponse
from django.template import Context
from mako.lookup import TemplateLookup
from mysite.settings import TEMPLATE_DIRS
def render_to_mako(t,c=None,context_instance=None):
path = TEMPLATE_DIRS
makolookup = TemplateLookup(directories=[path],output_encoding='utf- 8',input_encoding='utf-8')
mako_temp = makolookup.get_template(t)
if context_instance:
context_instance.update(c)
else:
context_instance = Context(c)
data = {}
for d in context_instance:data.update(d)
return HttpResponse(mako_temp.render(**data))
Jinja2django.py
from django.http import HttpResponse
from django.conf import settings
from jinja2 import Environment, ChoiceLoader, FileSystemLoader
# Setup environment
default_mimetype = getattr(settings, 'DEFAULT_CONTENT_TYPE')
# Create the Jinja2 Environment
env = Environment(
line_statement_prefix='%',
line_comment_prefix='##',
loader=ChoiceLoader([FileSystemLoader(path) for path in getattr(settings, 'TEMPLATE_DIRS', ())]))
def render_to_string(filename, context={}):
return env.get_template(filename).render(**context)
def render_to_jinja2(filename, context={},mimetype=default_mimetype, request = None):
if request: context['request'] = request
return HttpResponse(render_to_string(filename, context),mimetype=mimetype)
The view.py is similar as below
from draft.jinja2django import render_to_jinja2
def view1(request):
b = "helloworld"
return render_to_jinja2('testjinja.html', context={"test":b})
Starting from Django 1.2 you can create your custom template loader that returns your Template object. Doing that you can make django's render_to_response, render_to_string and counterparts render using your template system.
I am using this one:
https://gist.github.com/972162
It loads Jinja2 templates transparently and falls back to Django templates for admin, contrib and third-party apps.