【问题标题】:Rendering a form with django rest framework's ModelViewSet class insead of APIView使用 django rest 框架 ModelViewSet 类而不是 APIView 呈现表单
【发布时间】:2017-01-26 15:44:14
【问题描述】:

我想使用 rest 框架为我的 django 模型创建样板表单。

文档使用 APIView 显示它:http://www.django-rest-framework.org/topics/html-and-forms/#rendering-forms

但我想使用 ModelViewSet 以避免定义自定义操作方法。

这可能吗?你能分享一个例子吗?

这是我尝试过的。我的模型:

class Person(AbstractUser):
    pass

我的序列化器:

class PersonSerializer(serializers.HyperlinkedModelSerializer):
    class Meta:
        model = Person
        fields = ('first_name', 'last_name', 'email', 'groups')

我的看法:

class PersonViewSet(viewsets.ModelViewSet):
    """
    API endpoint that allows persons to be viewed or edited.
    """
    queryset = Person.objects.all().order_by('-date_joined')
    serializer_class = PersonSerializer
    renderer_classes = [TemplateHTMLRenderer]
    template_name = 'common/rest_create.html'

这是我的网址:

url(r'person_create_api/$', PersonViewSet.as_view({'get': 'create'}), name='person-create-api'),

我得到的错误是:

IntegrityError at /school/person_create_api/
duplicate key value violates unique constraint "school_person_username_key"
DETAIL:  Key (username)=() already exists.

当我将username 字段添加到序列化器字段时,我得到:

HTTP/1.0 400 Bad Request
Date: Tue, 20 Sep 2016 17:00:22 GMT
Server: WSGIServer/0.2 CPython/3.5.1+
X-Frame-Options: SAMEORIGIN
Vary: Cookie
Allow: GET, HEAD, OPTIONS
Content-Type: text/html; charset=utf-8

我正在使用 django 1.9 和最新的 DRF 3.4.6。

【问题讨论】:

  • 一旦成功,我将获取该视图的内容并在其他视图中使用它。
  • ModelViewSet 的基类如下:ModelViewSet > GenericViewSet > GenericAPIView > APIView。所以它确实继承自 APIView。
  • 您使用的是什么版本的 DRF 和 Django?您将 get 定义为 as_view 而不是在您创建的模型视图集上覆盖/重载它,这可能无法按您期望的方式执行。您也没有使用路由器,这是为 DRF 路由 API 端点的传统方式。他们甚至在文档 (django-rest-framework.org/api-guide/routers/#custom-routers) 中展示了如何创建自定义的。我也不知道Person 的序列化程序或模型是什么样的。你能把它包括进去吗?
  • tredzko 我添加了模型和序列化程序。我需要查看自定义路由器。
  • 尝试将“用户名”添加到“PersonSerializer”上的字段列表中,看看是否有帮助(您必须在创建时指定它)。当用户名被限制为唯一时,完整性错误似乎来自于尝试将空白用户名(因为它没有在序列化程序上公开)分配给多个 id。请记住,您是在告诉“获取”(默认行为是查看,而不是发布)尝试“创建”一个 Person,因此它可能无法获取任何值,因此可能会出错。

标签: django django-rest-framework


【解决方案1】:

首先,让 DRF 为您创建 url(这样可以防止错误配置 url):

from rest_framework.routers import DefaultRouter
router = DefaultRouter()
router.register(r'snippets', PersonViewSet)

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

这里是生成的网址:

^persons/$ [name='person-list']
^persons\.(?P<format>[a-z0-9]+)/?$ [name='person-list']
^persons/blank_form/$ [name='person-blank-form']
^persons/blank_form\.(?P<format>[a-z0-9]+)/?$ [name='person-blank-form']
^persons/(?P<pk>[^/.]+)/$ [name='person-detail']
^persons/(?P<pk>[^/.]+)\.(?P<format>[a-z0-9]+)/?$ [name='person-detail']

模型同上,视图如下:

class PersonViewSet(viewsets.ModelViewSet):
    """
    API endpoint that allows persons to be viewed or edited.
    """
    queryset = Person.objects.all().order_by('-date_joined')
    serializer_class = PersonSerializer
    template_name = 'common/rest_create.html'

    @list_route(renderer_classes=[renderers.TemplateHTMLRenderer])
    def blank_form(self, request, *args, **kwargs):
        serializer = PersonSerializer()
        return Response({'serializer': serializer})

注意,TemplateHtmlRenderer 是在方法级别设置的,而不是在类中全局设置,以便让它为其他方法/视图使用其他适当的渲染器。在 DRF 站点上作弊,serializer = PersonSerializer() 用于生成未绑定的表单。

这是模板:

{% load rest_framework %}

<html><body>    
<h1>New Person</h1>

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

</body></html>

您期望从 ModelViewSet 中获得的其他视图照常工作。

【讨论】:

  • 所以这种方法涉及向类添加方法并编写模板。我仍然很好奇如何使用开箱即用的功能来完成它。
猜你喜欢
  • 2016-06-20
  • 2021-01-16
  • 1970-01-01
  • 2016-03-29
  • 1970-01-01
  • 2022-08-14
  • 1970-01-01
  • 2020-12-20
  • 1970-01-01
相关资源
最近更新 更多