【问题标题】:Django view function execution jumps to different functionDjango视图函数执行跳转到不同的函数
【发布时间】:2019-07-31 21:27:04
【问题描述】:

我正在向现有 Django 项目添加新应用程序,但遇到了一些我无法调试的问题。回调错误是“AttributeError:'QuerySet'对象没有属性'META'”,但我不确定这是怎么回事。我今天已经为不同的 API 对象编写了 4 个这样的应用程序,并且没有任何问题。当我向函数添加 print() 调试消息时,我发现执行似乎在出错之前跳出我的lead_lists 视图函数并进入我的列表视图函数。

这是我的 list.views.py

def list(request):
    print("we're in lists view")
    lists = List.objects.all()
    print("lists saved for context")
    context = {'lists': lists}
    print("context created")
    return render(request, 'list.html', context) # fails here

def load_lists(request):
    api_lists = services.get_lists()
    print("api lists loaded")
    db_list_ids = list(List.objects.values_list('list_id', flat=True)) # jumps out of function here
    print("db lists loaded") # this never prints
    print(f"db_list_ids: {db_list_ids}")
    for api_list in api_lists:
        if api_list['id'] not in db_list_ids:
            api_list = services.transform_list(api_list)
            form = ListModelForm(api_list)
            if form.is_valid():
                form.save
            else:
                return HttpResponse(form.errors)
    print("exited load loop")
    lists = List.objects.all()
    print("load lists objects saved")
    context = {'lists': lists}
    print("load lists context saved")
    return render(request, 'load_lists.html', context)

预期的结果是,当我导航到 /list/load 时,它会运行 load_lists 视图函数。这是我从控制台得到的输出。

we're in lists view
lists saved for context
context created
[31/Jul/2019 16:20:32] "GET /list/ HTTP/1.1" 200 2458
api lists loaded
we're in lists view
lists saved for context
context created
Internal Server Error: /list/load/
Traceback (most recent call last):
  File "C:\Users\David.Wilcox\ongage-django\venv\lib\site-packages\django\core\handlers\exception.py", line 34, in inner
    response = get_response(request)
  File "C:\Users\David.Wilcox\ongage-django\venv\lib\site-packages\django\core\handlers\base.py", line 115, in _get_response
    response = self.process_exception_by_middleware(e, request)
  File "C:\Users\David.Wilcox\ongage-django\venv\lib\site-packages\django\core\handlers\base.py", line 113, in _get_response
    response = wrapped_callback(request, *callback_args, **callback_kwargs)
  File "C:\Users\David.Wilcox\ongage-django\ongage\list\views.py", line 19, in load_lists
    db_list_ids = list(List.objects.values_list('list_id', flat=True))
  File "C:\Users\David.Wilcox\ongage-django\ongage\list\views.py", line 14, in list
    return render(request, 'list.html', context)
  File "C:\Users\David.Wilcox\ongage-django\venv\lib\site-packages\django\shortcuts.py", line 36, in render
    content = loader.render_to_string(template_name, context, request, using=using)
  File "C:\Users\David.Wilcox\ongage-django\venv\lib\site-packages\django\template\loader.py", line 62, in render_to_string
    return template.render(context, request)
  File "C:\Users\David.Wilcox\ongage-django\venv\lib\site-packages\django\template\backends\django.py", line 61, in render
    return self.template.render(context)
  File "C:\Users\David.Wilcox\ongage-django\venv\lib\site-packages\django\template\base.py", line 169, in render
    with context.bind_template(self):
  File "c:\users\david.wilcox\appdata\local\programs\python\python37-32\Lib\contextlib.py", line 112, in __enter__
    return next(self.gen)
  File "C:\Users\David.Wilcox\ongage-django\venv\lib\site-packages\django\template\context.py", line 246, in bind_template
    updates.update(processor(self.request))
  File "C:\Users\David.Wilcox\ongage-django\venv\lib\site-packages\django\template\context_processors.py", line 40, in debug
    if settings.DEBUG and request.META.get('REMOTE_ADDR') in settings.INTERNAL_IPS:
AttributeError: 'QuerySet' object has no attribute 'META'
[31/Jul/2019 16:20:36] "GET /list/load/ HTTP/1.1" 500 103930

我原本以为因为使用了“list”这个词,玩的不是很好,所以我重构并重命名了我的变量,但错误是一样的。

【问题讨论】:

  • 你已经覆盖了 list 内置函数。

标签: html django python-3.x


【解决方案1】:

简短回答:请不要以 Python 内置函数命名您的视图,例如 list。您可以将视图函数重命名为view_lists

您在这里定义了一个名为 list 的函数。因此,如果您稍后在 load_lists 视图中使用 list(List.objects.values_list('list_id', flat=True)),您确实会调用视图函数,而不是内置函数,因为该标识符现在指向您的视图函数。

例如,您可以将其重命名为 view_lists,例如:

# rename view function

def view_lists(request):
    return render(request, 'list.html', {'lists': List.objects.all()})

def load_lists(request):
    api_lists = services.get_lists()
    db_list_ids = list(List.objects.values_list('list_id', flat=True))
    print(f"db_list_ids: {db_list_ids}")
    for api_list in api_lists:
        if api_list['id'] not in db_list_ids:
            api_list = services.transform_list(api_list)
            form = ListModelForm(api_list)
            if form.is_valid():
                form.save()
            else:
                return HttpResponse(form.errors)
    lists = List.objects.all()
    return render(request, 'load_lists.html', context = {'lists': lists})

请注意,您需要在表单上调用save() 函数,所以form.save()不是 form.save

PEP-8 建议在没有比内置名称更好的名称时添加尾随下划线:

如果函数参数的名称与保留关键字冲突,通常最好添加一个尾随下划线,而不是使用缩写或拼写错误。因此class_ 优于clss。 (也许更好的是使用同义词来避免这种冲突。)

(...)

如果您的公共属性名称与保留关键字冲突,请在您的属性名称后面附加一个下划线。这比缩写或损坏的拼写更可取。 (然而,尽管有这条规则,'cls' 是任何已知为类的变量或参数的首选拼写,尤其是类方法的第一个参数。)

【讨论】:

  • 谢谢!超级明显,但我盯着它太久了。当您处理与 python 内置函数共享名称的外部对象时,命名函数和变量的 Python 方法是什么?
  • @d-wilcox:PEP-8 建议添加尾随内标。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-09-26
  • 1970-01-01
  • 2010-10-12
  • 1970-01-01
  • 2011-11-05
相关资源
最近更新 更多