Skip to content

Instantly share code, notes, and snippets.

@kurtgn
Last active June 22, 2019 12:02
Show Gist options
  • Save kurtgn/84ecbacd983208caf4d691829d7f50a6 to your computer and use it in GitHub Desktop.
Save kurtgn/84ecbacd983208caf4d691829d7f50a6 to your computer and use it in GitHub Desktop.
Django-тег, запрещающий SQL в шаблонах
import contextlib
import json
from django.db import connection
from django import template
register = template.Library()
@contextlib.contextmanager
def assert_num_queries(number: int):
"""
Контекстный менеджер, который ломается, если его вложенный код
делает лишние запросы к БД
:param number: сколько запросов разрешено сделать внутри менеджера
(если 0 - то ни одного не разрешено)
"""
current_query_len = len(connection.queries)
try:
yield
finally:
new_query_len = len(connection.queries)
if new_query_len - current_query_len > number:
details = connection.queries[new_query_len-1:]
details_str = json.dumps(details, indent=4, ensure_ascii=False)
raise Exception(
f'Found unexpected query! {details_str}'
)
class NoDbAccessNode(template.Node):
def __init__(self, nodelist):
self.nodelist = nodelist
def render(self, context):
with assert_num_queries(0):
output = self.nodelist.render(context)
return output
@register.tag('nodb')
def nodb(parser, token):
"""
Тег, который выкидывает исключение, если внутри него есть запросы к БД
{% nodb %}
... код, который мы хотим изолировать от доступа к БД
{% endnodb %}
"""
nodelist = parser.parse(('endnodb',))
parser.delete_first_token()
return NoDbAccessNode(nodelist)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment