通常,PyCharm 自动完成(代码完成)适用于 Django 模板中的上下文变量。例如,如果上下文是
{"question": question}
,其中 question
是 Question
模型的实例,当我开始输入 {{ question. }}
时,PyCharm 将提供自动完成建议,如下所示:
但是,在我当前的 Django 项目中,PyCharm 自动完成功能无法用于 Django 模板中的上下文变量。即使按
Ctrl
+ Space
也不会弹出代码补全建议:
我认为我已经像往常一样在 PyCharm 中为 Django 配置了该项目的所有内容,尽管我可能是错误的。这是一个更大的项目,所以我怀疑项目结构本身的某些问题可能导致了问题。
其他便利功能仍在 Django 模板中使用,例如 Emmet 缩写、自动关闭
{{
和 {%
等。
起初,我怀疑问题是我的模型、视图等被分成了多个文件。例如,模型不是包含在单个
models.py
文件中,而是按如下方式组织:
models/
__init__.py
model_a.py
model_b.py
model_c.py
但是,我不认为这会导致自动完成失败,因为当我创建一个小型 Django 项目并以这种方式组织它时,自动完成仍然适用于 Django 模板中的上下文变量。
这是 PyCharm Professional 2023.3.3 的,虽然我刚刚更新到 2024.2.3 并且到目前为止仍然遇到同样的问题。
任何人都可以提出 PyCharm 自动完成对于 Django 模板中的上下文变量失败的一些原因吗?
经过一番尝试和错误,我的项目中已经完成了代码完成工作。
这是我发现的:
Django 模板中上下文变量的 PyCharm 代码完成在以下条件下工作:
render()
时render()
函数时据我所知,当使用 TemplateResponse()
或
HttpResponse()
(以及 django.template.loader
模块)而不是 render()
时,它不会工作。 当模板路径作为变量而不是字符串文字传递给
render()
时,它也不起作用。
例如,当视图编写如下时,代码完成会起作用:
def detail(request, question_id):
question = get_object_or_404(Question, pk=question_id)
return render(request, "polls/detail.html", {"question": question})
将 context
作为变量传递也可以,所以这也有效:
def detail(request, question_id):
question = get_object_or_404(Question, pk=question_id)
context = {"question": question}
return render(request, "polls/detail.html", context)
但是,当视图以下列任何一种方式编写时,代码完成会失败:
例如,当将template_name
作为变量传递给
render()
而不是作为字符串文字时:
def detail(request, question_id):
question = get_object_or_404(Question, pk=question_id)
template_name = "polls/detail.html"
return render(request, template_name, {"question": question})
例如,当使用 TemplateResponse()
代替
render()
时:
def detail(request, question_id):
question = get_object_or_404(Question, pk=question_id)
return TemplateResponse(request, "polls/detail.html", {"question": question})
例如,当像这样使用 HttpResponse()
时:
def detail(request, question_id):
question = get_object_or_404(Question, pk=question_id)
template = loader.get_template('polls/detail.html')
return HttpResponse(template.render({"question": question}, request))
但是为什么呢?
我认为TemplateResponse()
的代码完成失败可能与它如何实现延迟渲染有关。 也许使用
HttpResponse()
(以及
django.template.loader
模块)时的失败也是出于类似的原因。我不确定为什么代码完成会失败,除非将
template_name
作为字符串文字直接提供给
render
。 看来静态代码分析应该能够弄清楚它是否作为在同一视图中使用字符串文字定义的变量传递。
注意事项
如果您有至少两个使用同一模板的视图,则需要注意以下几点:即使只有一个视图使用
render()
template_name
内使用
render()
的字符串文字),
代码补全也将起作用。 这很令人困惑,因为其他视图可以使用
TemplateResponse()
,例如,上下文变量的代码完成在相应的模板中仍然可以正常工作。
error_message
内传递了
context
变量,但另一个视图则没有。 PyCharm 将自动完成模板中的
error_message
变量,而不会警告某些视图不会在
context
中传递此变量。
结语
除了更改视图以使用render()
(来自
django.shortcuts
)并确保字符串文字用于
template_name
中的
render()
之外,我没有对项目结构进行任何更改。我仍然不相信 PyCharm 不应该能够在模板中完成上下文变量的代码,除非遵循这个神奇的公式。 我不确定这是否是一个错误,或者可能只是我不理解 PyCharm。