在 Django REST Framework 中更新/放置请求

Vas*_*aur 0 python django rest django-models django-rest-framework

我是 Django REST Framework 的新手,并在我正在开发的新项目中尝试使用它。因此,根据官方教程,我尝试创建几个 get/post/put 请求,但使用 put 请求时出现以下错误:

预期使用名为“pk”的 URL 关键字参数调用视图 ExampleUpdateView。修复您的 URL 配置,或.lookup_field正确设置视图上的属性。

这是我必需的文件:

models.py

class ExampleModel(models.Model):
    foo_field = models.CharField(primary_key=True, max_length=15)
    bar_field = models.CharField(max_length=30)
    last_updated_by = models.CharField(max_length=15)
    last_updated_on = models.DateTimeField()

    class Meta:
        managed = True
        db_table = 'example_db'
        unique_together = (('foo_field', 'bar_field'),)
Run Code Online (Sandbox Code Playgroud)

serializers.py

class ExampleSerializer(serializers.ModelSerializer):
    class Meta:
        model = ExampleModel
        fields = ('foo_field', 'bar_field', 'last_updated_by', 'last_updated_on')
Run Code Online (Sandbox Code Playgroud)

urls.py

url(r'^get_example/$', views.ExampleCreateView.as_view()),
url(r'^update_example/(?P<pk>\d+)/$',views.ExampleUpdateView.as_view()),
Run Code Online (Sandbox Code Playgroud)

views.py

class ExampleCreateView(generics.CreateAPIView):
    serializer_class = ExampleSerializer
    queryset = ExampleModel.objects.all()

class ExampleUpdateView(generics.UpdateAPIView):
    queryset = ExampleModel.objects.all()
    serializer_class = ExampleSerializer
Run Code Online (Sandbox Code Playgroud)

我认为我可能遇到的问题是我有一个复合键。我尝试了其他通用视图(CreateAPIView 和 ListAPIView),它们工作得非常好。我需要更新def_update方法吗?我需要改变什么吗serializers.py

这是我从 GET 请求中获取并尝试更新的现有 JSON 对象:

{
    "foo_field": "john",
    "bar_field": "doe",
    "last_updated_by": "batman",
    "last_updated_on": "2017-02-09"
}
Run Code Online (Sandbox Code Playgroud)

我查看了以下重复项,但这些解决方案似乎都不适合我:

Django Rest Framework:不清楚的错误消息

Django REST Updateview 与 PUT POST

如何使用 UpdateView 更新 Django 模型?

cez*_*zar 5

首先,我将重构您的代码并展示代码示例。之后我将解释这些变化。

models.py

class ExampleModel(models.Model):
    foo_field = models.CharField(primary_key=True, max_length=15)
    # rest ...
Run Code Online (Sandbox Code Playgroud)

您已设置foo_field为主键。使用字符串 ( VARCHAR) 作为主键是一个不好的做法。强烈建议使用代理键。这将由 Django 自动完成。它添加一个字段id作为主键。

现在将按serializers.py原样工作。无需更改。也views.py应该无需更改即可工作。foo_field不过,我将介绍作为主键的选项。

views.py

类ExampleUpdateView(generics.UpdateAPIView):
    # 休息 ...
    查找字段 = `foo_field`

您也可以忽略这一点,但在您的urls.py.

urls.py

url(r'^示例/$',views.ExampleCreateView.as_view()),
url(r'^示例/(?P<pk>\d+)/$',views.ExampleUpdateView.as_view()),

为了使 Web 服务实现 RESTful,它们必须遵守 REST 原则。最重要的规则之一是我们不应在 URL 中使用动词来描述操作。另一个约定是使用复数资源名称来描述集合,并使用标识符来访问单个资源。

您的资源称为example,因此我们使用Examples作为集合名称。URL 中没有像 get 或 update 这样的动词。HTTP 方法负责执行正确的操作。

如果您想用foo_field作主键,则必须更改更新视图的 url:

url(r'^examples/(?P<pk>[\w-]+)/$',views.ExampleUpdateView.as_view()),
Run Code Online (Sandbox Code Playgroud)

这是因为 yourfoo_field是一个CharField(或字符串),因此传递给它的参数应该与任何字母数字字符 ( \w) 和连字符 ( -) 匹配。
如果您愿意,您可以foo_field在 url 正则表达式中使用 as 命名组pk。请注意,根据您的观点进行调整,为lookup_field和设置正确的值lookup_url_kwarg

我再次强烈建议使用代理键并让 Django 来完成此任务。

现在您可以理解为什么ListAPIView并且CreateAPIView有效了。它们不需要传递给 url 的参数并且被正确调用。
UpdateAPIView无法工作,因为匹配的网址仅接受数字并且与您的主键不匹配foo_field