检查字符串中是否仅指定了Django模板变量

时间:2019-05-20 08:01:40

标签: python django

我正在研究可配置的电子邮件模板,需要验证内容中是否仅使用available_variables。因此,如果用户输入{{ apple }},则表单应返回ValidationError('This variable is unavailable')

models.py:

email_content = models.TextField()

forms.py:

def clean_email_content(self):
     email_content = self.cleaned_data['email_content']
     available_variables = ['{{ company_name }}', '{{ user_name }}']
     required_variables = ['{{ company_name }}']
     for required_variable in required_variables:
        if not required_variable in email_content:
                raise forms.ValidationError("{} is required".format(required_variable))
     # how to check if there are only `available_variables` in the content?

TL; DR

email_content不能包含{{中指定的变量(以}}开头并以available_variables结尾的字符串)

我应该使用正则表达式还是可以使用Django模板引擎中的某些方法对此进行验证?

3 个答案:

答案 0 :(得分:3)

您可能想改用模板引擎的词法分析器(nb:django 1.11代码,如果使用django 2.x,则可能需要改编):

from django.template import base
lexer = base.Lexer("{{ var_one }} is one {% if var_two %}{{ var_two|upper }} is two {% endif %}")
tokens = lexer.tokenize()
for t in tokens:
    if t.token_type == base.TOKEN_VAR:
        print("{}: {}".format(t, t.contents)

我留给您阅读template.base代码以了解其他有用的功能...

在您的验证方法中,您也绝对想立即捕获所有错误(而不是在发现错误后立即引发),以便用户可以立即修复所有错误(除非您真的想让用户发疯),是)。

最后,正如Gasanov在他的回答中所建议的那样,您还希望使用集合来查找缺少的必需变量和非法变量-这比顺序查找要有效得多。

答案 1 :(得分:1)

我们可以使用正则表达式从email_content中查找所有标签。之后,我们将它们转换为set并从中减去所有available_variables来查找所有不正确的值。如果存在-我们抛出ValidationError

请注意,available_variables本身就是set,仅包含标签,没有大括号。
我们的正则表达式会检查方括号和标签之间是否有空格,因此您的用户不应作弊。

import re

def clean_email_content(self):
        email_content = self.cleaned_data['email_content']
        available_variables = {'company_name', 'user_name'}
        finds = re.findall(r"{{[ ]*(.*?)[ ]*}}", email_content)
        invalid_tags = set(finds) - available_variables
        if invalid_tags:
            raise forms.ValidationError(
                "Should not contain invalid tags: " + str(invalid_tags)
            )
        return email_content

答案 2 :(得分:-2)

也许您可以这样做:

@foreach($blockItemsContent as $blockItemContent)
    @if($blockItemContent->item_type == 'title')
        <h1>{{ $blockItemContent->content }}</h1>
    @endif
@endforeach

以上代码的作用是,如果email_content中有任何可用内容中没有的变种,则会引发异常