Python Django REST框架中的更新/放置请求
我是Django REST框架的新手,正在为一个新项目尝试它。因此,根据官方教程,我尝试创建几个get/post/put请求,但是使用put请求,我得到以下错误: 应使用名为“pk”的URL关键字参数调用view ExampleUpdateView。修复URL配置,或在视图上正确设置Python Django REST框架中的更新/放置请求,python,django,rest,django-models,django-rest-framework,Python,Django,Rest,Django Models,Django Rest Framework,我是Django REST框架的新手,正在为一个新项目尝试它。因此,根据官方教程,我尝试创建几个get/post/put请求,但是使用put请求,我得到以下错误: 应使用名为“pk”的URL关键字参数调用view ExampleUpdateView。修复URL配置,或在视图上正确设置.lookup\u字段属性 以下是我需要的文件: models.py class ExampleModel(models.Model): foo_field = models.CharField(primar
.lookup\u字段
属性
以下是我需要的文件:
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'),)
class ExampleSerializer(serializers.ModelSerializer):
class Meta:
model = ExampleModel
fields = ('foo_field', 'bar_field', 'last_updated_by', 'last_updated_on')
url(r'^get_example/$', views.ExampleCreateView.as_view()),
url(r'^update_example/(?P<pk>\d+)/$',views.ExampleUpdateView.as_view()),
class ExampleCreateView(generics.CreateAPIView):
serializer_class = ExampleSerializer
queryset = ExampleModel.objects.all()
class ExampleUpdateView(generics.UpdateAPIView):
queryset = ExampleModel.objects.all()
serializer_class = ExampleSerializer
class ExampleUpdateView(generics.UpdateAPIView):
# rest ...
lookup_field = `foo_field`
url(r'^examples/$', views.ExampleCreateView.as_view()),
url(r'^examples/(?P<pk>\d+)/$',views.ExampleUpdateView.as_view()),
序列化程序.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'),)
class ExampleSerializer(serializers.ModelSerializer):
class Meta:
model = ExampleModel
fields = ('foo_field', 'bar_field', 'last_updated_by', 'last_updated_on')
url(r'^get_example/$', views.ExampleCreateView.as_view()),
url(r'^update_example/(?P<pk>\d+)/$',views.ExampleUpdateView.as_view()),
class ExampleCreateView(generics.CreateAPIView):
serializer_class = ExampleSerializer
queryset = ExampleModel.objects.all()
class ExampleUpdateView(generics.UpdateAPIView):
queryset = ExampleModel.objects.all()
serializer_class = ExampleSerializer
class ExampleUpdateView(generics.UpdateAPIView):
# rest ...
lookup_field = `foo_field`
url(r'^examples/$', views.ExampleCreateView.as_view()),
url(r'^examples/(?P<pk>\d+)/$',views.ExampleUpdateView.as_view()),
url.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'),)
class ExampleSerializer(serializers.ModelSerializer):
class Meta:
model = ExampleModel
fields = ('foo_field', 'bar_field', 'last_updated_by', 'last_updated_on')
url(r'^get_example/$', views.ExampleCreateView.as_view()),
url(r'^update_example/(?P<pk>\d+)/$',views.ExampleUpdateView.as_view()),
class ExampleCreateView(generics.CreateAPIView):
serializer_class = ExampleSerializer
queryset = ExampleModel.objects.all()
class ExampleUpdateView(generics.UpdateAPIView):
queryset = ExampleModel.objects.all()
serializer_class = ExampleSerializer
class ExampleUpdateView(generics.UpdateAPIView):
# rest ...
lookup_field = `foo_field`
url(r'^examples/$', views.ExampleCreateView.as_view()),
url(r'^examples/(?P<pk>\d+)/$',views.ExampleUpdateView.as_view()),
我想我可能的问题是我有一个复合键。我尝试了其他通用视图(CreateAPIView和ListAPIView),它们工作得非常好。我是否需要更新def_update
方法?我是否需要更改serializers.py中的任何内容
这是我从GET请求中获得的一个现有JSON对象,正在尝试更新:
{
"foo_field": "john",
"bar_field": "doe",
"last_updated_by": "batman",
"last_updated_on": "2017-02-09"
}
我查看了以下副本,但这些解决方案似乎都不适合我:
使用update()
和您的UpdateAPIView
class ExampleUpdateView(generics.UpdateAPIView):
queryset = ExampleModel.objects.all()
serializer_class = ExampleSerializer
def update(self, request, *args, **kwargs):
instance = self.get_object()
instance.foo_field = request.data.get("foo_field")
instance.bar_field = request.data.get("bar_field")
instance.last_updated_by = request.data.get("last_updated_by")
instance.last_updated_on = request.data.get("last_updated_on")
instance.save()
serializer = self.get_serializer(instance)
serializer.is_valid(raise_exception=True)
self.perform_update(serializer)
return Response(serializer.data)
使用update()
和您的updateaview
class ExampleUpdateView(generics.UpdateAPIView):
queryset = ExampleModel.objects.all()
serializer_class = ExampleSerializer
def update(self, request, *args, **kwargs):
instance = self.get_object()
instance.foo_field = request.data.get("foo_field")
instance.bar_field = request.data.get("bar_field")
instance.last_updated_by = request.data.get("last_updated_by")
instance.last_updated_on = request.data.get("last_updated_on")
instance.save()
serializer = self.get_serializer(instance)
serializer.is_valid(raise_exception=True)
self.perform_update(serializer)
return Response(serializer.data)
首先,我将重构您的代码并给出代码示例。之后我会解释这些变化
models.py
class ExampleModel(models.Model):
foo_field = models.CharField(primary_key=True, max_length=15)
# rest ...
您也可以忽略这一点,但对url.py
进行一些更改是很重要的
url.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'),)
class ExampleSerializer(serializers.ModelSerializer):
class Meta:
model = ExampleModel
fields = ('foo_field', 'bar_field', 'last_updated_by', 'last_updated_on')
url(r'^get_example/$', views.ExampleCreateView.as_view()),
url(r'^update_example/(?P<pk>\d+)/$',views.ExampleUpdateView.as_view()),
class ExampleCreateView(generics.CreateAPIView):
serializer_class = ExampleSerializer
queryset = ExampleModel.objects.all()
class ExampleUpdateView(generics.UpdateAPIView):
queryset = ExampleModel.objects.all()
serializer_class = ExampleSerializer
class ExampleUpdateView(generics.UpdateAPIView):
# rest ...
lookup_field = `foo_field`
url(r'^examples/$', views.ExampleCreateView.as_view()),
url(r'^examples/(?P<pk>\d+)/$',views.ExampleUpdateView.as_view()),
这是因为您的foo\u字段
是一个CharField
(或字符串),因此传递给它的参数应该匹配任何字母数字字符(\w
)和连字符(-
)。
如果愿意,您可以在url正则表达式中使用foo_字段
作为命名组,而不是pk
。请注意,在您的视图中对其进行调整,为lookup\u字段
和lookup\u url\u kwarg
设置正确的值
我再次强烈建议使用代理键,让Django来完成这项任务
现在您可以理解为什么ListAPIView
和createapieview
起作用了。它们不需要传递到url的参数,并且被正确调用。
您的updateAliview
无法工作,因为匹配的url只接受数字,并且与您的主键foo\u字段不匹配首先,我将重构您的代码并展示代码示例。之后我会解释这些变化
models.py
class ExampleModel(models.Model):
foo_field = models.CharField(primary_key=True, max_length=15)
# rest ...
您也可以忽略这一点,但对url.py
进行一些更改是很重要的
url.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'),)
class ExampleSerializer(serializers.ModelSerializer):
class Meta:
model = ExampleModel
fields = ('foo_field', 'bar_field', 'last_updated_by', 'last_updated_on')
url(r'^get_example/$', views.ExampleCreateView.as_view()),
url(r'^update_example/(?P<pk>\d+)/$',views.ExampleUpdateView.as_view()),
class ExampleCreateView(generics.CreateAPIView):
serializer_class = ExampleSerializer
queryset = ExampleModel.objects.all()
class ExampleUpdateView(generics.UpdateAPIView):
queryset = ExampleModel.objects.all()
serializer_class = ExampleSerializer
class ExampleUpdateView(generics.UpdateAPIView):
# rest ...
lookup_field = `foo_field`
url(r'^examples/$', views.ExampleCreateView.as_view()),
url(r'^examples/(?P<pk>\d+)/$',views.ExampleUpdateView.as_view()),
这是因为您的foo\u字段
是一个CharField
(或字符串),因此传递给它的参数应该匹配任何字母数字字符(\w
)和连字符(-
)。
如果愿意,您可以在url正则表达式中使用foo_字段
作为命名组,而不是pk
。请注意,在您的视图中对其进行调整,为lookup\u字段
和lookup\u url\u kwarg
设置正确的值
我再次强烈建议使用代理键,让Django来完成这项任务
现在您可以理解为什么ListAPIView
和createapieview
起作用了。它们不需要传递到url的参数,并且被正确调用。
您的updateAliview
无法工作,因为匹配的url只接受数字,并且与您的主键foo\u字段不匹配您的url.py
是一个明显的反模式。那不是休息!你没有把动词放进URL!HTTP请求方法应该映射到CRUD:POST-CREATE;获取-检索;放置-更新;DELETE-DELETE。您已将foo_字段
设置为主键,因此不使用复合键。Django不支持复合键。您拥有的是unique\u合在一起
,这是unique键
,而不是复合键。顺便问一下,使用字符串作为主键是一种不好的做法。您需要使用createapieview
和updateapiew
的真正原因是什么?为什么不ListCreateAPIView
和RetrieveUpdatedStroyaPiView
?或者为什么不直接转到视图集?您的特殊要求是什么?CreateAPIView和UpdatePapiView只是示例。我尝试使用RetrieveUpdatedStroyapiView,但后者中的put请求仍然会给我相同的错误YourURL.py
是一个明显的反模式。那不是休息!你没有把动词放进URL!HTTP请求方法应该映射到CRUD:POST-CREATE;获取-检索;放置-更新;DELETE-DELETE。您已将foo_字段
设置为主键,因此不使用复合键。Django不支持复合键。您拥有的是unique\u合在一起
,这是unique键
,而不是复合键。顺便问一下,使用字符串作为主键是一种不好的做法。您需要使用createapieview
和updateapiew
的真正原因是什么?为什么不ListCreateAPIView
和RetrieveUpdatedStroyaPiView
?或者为什么不直接转到视图集?您的特殊要求是什么?CreateAPIView和UpdatePapiView只是示例。我尝试了RetrieveUpdatedStroyapiView,但是后者中的put请求仍然会给我相同的错误。非常感谢您提供了详细的答案。我现在明白了为什么ListApiew和ListApiew可以工作,而UpdateApiew不能。不幸的是,尽管我很想使用代理键(在本例中是Django的Autofield),但我无法选择它(我的技术负责人说了一个硬不)。我无法控制数据库(现在使用inspectdb)。我必须使用复合键,在VARCHAR中也是如此。@VasuGaur在这种情况下使用