【问题标题】:DRF forms - 'str' object has no attribute 'data'DRF 表单 - 'str' 对象没有属性 'data'
【发布时间】:2015-11-29 03:53:07
【问题描述】:

我正在尝试使用此处找到的示例 - http://www.django-rest-framework.org/topics/html-and-forms/

我实际上是从示例中剪切/粘贴,将其更改为我自己的模型 -

我正在通过 base.html 中的以下代码访问表单 -

{% include 'dashboard/widget_detail.html' %}

widget_details.html

{% load rest_framework %}

<h1>Profile - {{ widget.name }}</h1>

<form action="{% url 'widget-detail' pk=widget.pk '%}" method="POST">
    {% csrf_token %}
    {% render_form serializer %}
    <input type="submit" value="Save">
</form>

views.py

class WidgetDetail(APIView):
    renderer_classes = [TemplateHTMLRenderer]
    template_name = 'dashboard/widget_detail.html'

    def get(self, request, pk):
        widget= get_object_or_404(Widget, pk=pk)
        serializer = WidgetSerializer(widget)
        return Response({'serializer': serializer, 'widget': widget})

    def post(self, request, pk):
        widget= get_object_or_404(Widget, pk=pk)
        serializer = WidgetSerializer(widget)
        if not serializer.is_valid():
            return Response({'serializer': serializer, 'widget': widget})
        return redirect('widget-list')

当尝试为我的 base.html 加载 URL 时,我得到以下回溯 -

Traceback:
File "/opt/enterpass_app/lib/python2.7/site-packages/django/core/handlers/base.py" in get_response
  132.                     response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "/opt/enterpass/gui/views.py" in display_base
  37.                           context_instance=RequestContext(request))
File "/opt/enterpass_app/lib/python2.7/site-packages/django/shortcuts.py" in render_to_response
  45.             using=using)
File "/opt/enterpass_app/lib/python2.7/site-packages/django/template/loader.py" in render_to_string
  115.                         template_name, context, context_instance, dirs, dictionary)
File "/opt/enterpass_app/lib/python2.7/site-packages/django/template/engine.py" in render_to_string
  221.             return t.render(context_instance)
File "/opt/enterpass_app/lib/python2.7/site-packages/django/template/base.py" in render
  209.                     return self._render(context)
File "/opt/enterpass_app/lib/python2.7/site-packages/django/template/base.py" in _render
  201.         return self.nodelist.render(context)
File "/opt/enterpass_app/lib/python2.7/site-packages/django/template/base.py" in render
  903.                 bit = self.render_node(node, context)
File "/opt/enterpass_app/lib/python2.7/site-packages/django/template/debug.py" in render_node
  79.             return node.render(context)
File "/opt/enterpass_app/lib/python2.7/site-packages/django/template/loader_tags.py" in render
  159.                 return template.render(context)
File "/opt/enterpass_app/lib/python2.7/site-packages/django/template/base.py" in render
  211.                 return self._render(context)
File "/opt/enterpass_app/lib/python2.7/site-packages/django/template/base.py" in _render
  201.         return self.nodelist.render(context)
File "/opt/enterpass_app/lib/python2.7/site-packages/django/template/base.py" in render
  903.                 bit = self.render_node(node, context)
File "/opt/enterpass_app/lib/python2.7/site-packages/django/template/debug.py" in render_node
  79.             return node.render(context)
File "/opt/enterpass_app/lib/python2.7/site-packages/django/template/defaulttags.py" in render
  507.                         six.reraise(*exc_info)
File "/opt/enterpass_app/lib/python2.7/site-packages/django/template/defaulttags.py" in render
  493.             url = reverse(view_name, args=args, kwargs=kwargs, current_app=current_app)
File "/opt/enterpass_app/lib/python2.7/site-packages/django/core/urlresolvers.py" in reverse
  578.     return force_text(iri_to_uri(resolver._reverse_with_prefix(view, prefix, *args, **kwargs)))
File "/opt/enterpass_app/lib/python2.7/site-packages/django/core/urlresolvers.py" in _reverse_with_prefix
  495.                              (lookup_view_s, args, kwargs, len(patterns), patterns))

Exception Type: NoReverseMatch at /dashboard/
Exception Value: Reverse for 'widget-detail' with arguments '()' and keyword arguments '{u'pk': ''}' not found. 2 pattern(s) tried: [u'api/widgets/(?P<pk>[^/.]+)\\.(?P<format>[a-z0-9]+)/?$', u'api/widgets/(?P<pk>[^/.]+)/$']

我不知道我错过了什么/做错了什么。

我可以访问http://localhost/api/widgets/5没问题(例如)

更新 - 如果我从表单中删除 PK 值 -

<form action="{% url 'api:widget-detail' %}" method="POST">
    {% csrf_token %}
    {% render_form serializer %}
    <input type="submit" value="Save">
</form>

我收到以下错误 -

'str' object has no attribute 'data'

这很有意义,因为我还没有数据。我想要的只是一个空白表格,使用我的序列化程序作为后端来填写和“保存”。这有多难?!

包括我的 urls.py 从哪里解析 -

router = routers.DefaultRouter()
router.register(r'widgets', views.WidgetViewSet)

urlpatterns = [
    url(r'^', include(router.urls)),
]

【问题讨论】:

  • 第一个错误是告诉您没有与您尝试访问的 URL 匹配的 URL 模式。您的表单位于哪个 URL,您的 urls.py 是什么样的?

标签: django django-rest-framework


【解决方案1】:

错误信息给你一个线索;它说它使用空字符串作为pk 参数。这意味着由于某种原因 widget.pk 正在评估为空。

【讨论】:

  • 嘿,没有PK,因为我想要一个空白表格,然后我可以将自己的数据放入并发布。我找到了这个 stackoverflow http://stackoverflow.com/questions/30047855/django-rest-framework-form ,看起来我要问的是不可能的?如果我去http://localhost/api/widgets/,它会给我一个列表和底部的空白表格,我可以填写后发布。我想要的只是能够在某个地方的另一个模板中使用那个空白表单。
  • 这当然是完全可能的,但是您不应该尝试提交到需要 PK 的详细视图。您需要在您的 urls.py 中使用另一个模式,该模式在 /api/widgets 处接受 POST,而不需要 /5。
  • 所以问题在于它将我的帖子解析为[u'api/widgets/(?P&lt;pk&gt;[^/.]+)\\.(?P&lt;format&gt;[a-z0-9]+)/?$', u'api/widgets/(?P&lt;pk&gt;[^/.]+)/$'] 而不仅仅是api/widgets?
  • 是的,因为这是你告诉它的。你需要一个不同的模式,没有?P&lt;pk&gt;...。
猜你喜欢
  • 1970-01-01
  • 2020-07-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-04-25
  • 1970-01-01
  • 2015-09-11
相关资源
最近更新 更多