Django 中遇到的問題(1)TypeError: context must be a dict rather than Context.

1 . TypeError: context must be a dict rather than Context.

翻譯:上下文必須是一個字段,而不是一個Context實例對象
Django版本 1.11
報錯的代碼來自views.py:

def current_datetime(request):
     now = datetime.datetime.now()
     t = get_template("ctime.html") ##get_template() 方法可以直接得到人Template 實例
     ctx = Context({'now':now})
     html = t.render(ctx) #render 傳入 ctx 對象做爲參數
     return HttpResponse(html)

報錯信息:
Traceback (most recent call last):
File “D:\python3.6\lib\site-packages\django\core\handlers\exception.py”, line 41, in inner
response = get_response(request)
File “D:\python3.6\lib\site-packages\django\core\handlers\base.py”, line 187, in _get_response
response = self.process_exception_by_middleware(e, request)
File “D:\python3.6\lib\site-packages\django\core\handlers\base.py”, line 185, in _get_response
response = wrapped_callback(request, *callback_args, **callback_kwargs)
File “E:\python_workspace\sfweb\sfweb\books\views.py”, line 18, in current_datetime
html = t.render(ctx)
File “D:\python3.6\lib\site-packages\django\template\backends\django.py”, line 64, in render
context = make_context(context, request, autoescape=self.backend.engine.autoescape)
File “D:\python3.6\lib\site-packages\django\template\context.py”, line 287, in make_context
raise TypeError(‘context must be a dict rather than %s.’ % context.class.name)
TypeError: context must be a dict rather than Context.

錯誤原因:
代碼來自django book 2.0 按理說,書說不應該出錯 從stackoverflow 中知道,問題出在版本上
本書基於django 1.1 ,而本機安裝最新django 1.11版本

點開D:\python3.6\lib\site-packages\django\template\backends\django.py
從django 1.11源碼分析一下 :

class Template(object):

    def __init__(self, template, backend):
        self.template = template
        self.backend = backend

    @property
    def origin(self):
        return self.template.origin

    def render(self, context=None, request=None):
        context = make_context(context, request, autoescape=self.backend.engine.autoescape)
        try:
            return self.template.render(context)
        except TemplateDoesNotExist as exc:
            reraise(exc, self.backend)

context = make_context(context, request, autoescape=self.backend.engine.autoescape)中可以看出 ,render 方法傳入的context 參數 做爲了make_context()方法中,再看看 make_context()方法的源碼:
注意:這裏的Template 不是django.template.Template ,參數template 應該是django.template.Template 的實例

def make_context(context, request=None, **kwargs):
    """
    Create a suitable Context from a plain dict and optionally an HttpRequest.
    """
    if context is not None and not isinstance(context, dict):
        raise TypeError('context must be a dict rather than %s.' % context.__class__.__name__)
    if request is None:
        context = Context(context, **kwargs)
    else:
        # The following pattern is required to ensure values from
        # context override those from template context processors.
        original_context = context
        context = RequestContext(request, **kwargs)
        if original_context:
            context.push(original_context)
    return context

從if context is not None and not isinstance(context, dict) 中我們可以判斷 ,參數的context() 必須是一個字典類型(到這裏,我們就可以確定Template.render()中的context 參數爲什麼必須是字典了) ,make_context() 返回的是一個Context 或者基子類 RequestContext 實例對象

再回到上面的 render() :返回Template.template.render(Context)
即回到了我們熟悉的 django.template.Template.render(Context)

正確的代碼:

def current_datetime(request):
     now = datetime.datetime.now()
     t = get_template("ctime.html") ##get_template() 方法可以直接得到人Template 實例,但是這個不是django.template.Template實例
     #ctx = Context({'now':now})
     html = t.render({'now':now})
     return HttpResponse(html)

前臺正常!!!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章