[英]DJango REST Framework: How to write Create, List, Update and Delete with ModelViewSet
I'm still new to python/django and currently I'm trying to add REST API using django rest framework. 我还是python / django的新手,目前我正在尝试使用django rest框架添加REST API。 This is currently what I have: 这是我现在拥有的:
urls.py urls.py
actions_url = {'actions': {'get': 'list', 'post': 'create'}}
actions_obj = {'actions': {'get': 'retrieve', 'delete': 'destroy', 'put': 'update'}}
urlpatterns = [
path('book', BookViewSet.as_view(**actions_url)),
path('book/<str:isbn>', BookViewSet.as_view(**actions_obj))
]
models.py (The model doesn't have PK) models.py(模型没有PK)
class Book(models.Model):
BNAME = models.CharField(
db_column='BNAME',
max_length=30,
default='')
BISBN = models.CharField(
db_column='BISBN',
max_length=10,
default='')
views.py views.py
class BookSerializer(serializers.ModelSerializer):
name = serializers.CharField(source="BNAME")
isbn = serializers.CharField(source="BISBN")
class Meta:
model = models.Book
fields = ('name', 'isbn')
class BookViewSet(viewsets.ModelViewSet)
queryset = Book.objects.all()
serializer_class = BookSerializer
def list(self, request):
return queryset
def create(self, request):
pass
def retrieve(self, request, *args, **kwargs):
pass
def update(self, request, *args, **kwargs):
pass
def destroy(self, request, *args, **kwargs):
pass
So now my questions are: 所以现在我的问题是:
def create(self, request)
in the BookViewSet
for example, I assume when I make a POST /book
it will do nothing? 例如,如果我没有在BookViewSet
包含def create(self, request)
,我假设当我制作POST /book
它什么都不做? create
, retrieve
, update
, destroy
. 我正在努力去理解create
, retrieve
, update
, destroy
。 For example if I make a PUT /book/123
with params: { isbn: '123', name: 'test'}
, what do I need to do in def update
to retrieve those data from request then update data to database? 例如,如果我使用params制作PUT /book/123
: { isbn: '123', name: 'test'}
,在def update
需要做什么才能从请求中检索这些数据然后将数据更新到数据库? isbn
and make sure it is unique/no duplicate before saving a record/update it to database, what should I do? 我想在保存记录/将其更新到数据库之前验证isbn
并确保它是唯一的/没有重复的,我该怎么办? I tried reading about Validator: https://www.django-rest-framework.org/api-guide/validators/ and looks like I need to update serializer: 我尝试阅读Validator: https : //www.django-rest-framework.org/api-guide/validators/ ,看起来我需要更新序列化器: class BookSerializer(serializers.ModelSerializer):
name = serializers.CharField(source="BNAME")
isbn = serializers.CharField(source="BISBN", validators=[<UniqueValidator(queryset=Book.objects.all())>])
class Meta:
model = models.Book
fields = ('name', 'isbn')
Is this correct? 这个对吗?
isbn
and name
are unique together, I assume this is what I need to do: 与上一个问题类似,但现在我想确保isbn
和name
一起是唯一的,我认为这是我需要做的: class BookSerializer(serializers.ModelSerializer):
name = serializers.CharField(source="BNAME")
isbn = serializers.CharField(source="BISBN")
class Meta:
model = models.Book
fields = ('name', 'isbn')
validators = [
UniqueTogetherValidator(
queryset=Book.objects.all(),
fields=('name', 'isbn')
)
]
Is this correct? 这个对吗?
Thanks 谢谢
Your implementation of create(self, request, *args, **kwargs)
will do nothing because the function is empty, it won't even return a response. 你的create(self, request, *args, **kwargs)
实现什么都不做,因为函数是空的,它甚至不会返回响应。
You don't have to put anything in create
, list
, retrieve
, update
, partial_update
, and destroy
because you're using the ModelViewSet
class. 您不必在create
, list
, retrieve
, update
, partial_update
和destroy
放置任何内容,因为您正在使用ModelViewSet
类。 The ModelViewSet
provides a default implementation for all of them. ModelViewSet
为所有这些提供了默认实现。 If you really want to keep your overrides though you could use this implementation instead: 如果你真的想保留你的覆盖,你可以使用这个实现:
def create(self, request, *args, **kwargs):
"""You could add some documentation here"""
return super().create(request, *args, **kwargs)
We're using super()
because it is calling the parent implementation of create
. 我们使用的是super()
因为它调用了create
的父实现。
unique=True
on the model field rather than adding the validator to the serializer. 你正在做的是正确的,让我补充一点,我个人会在模型字段上放置一个unique=True
,而不是将验证器添加到序列化器中。 Rest Framework is smart enough that the serializer will inspect the model field and add the unique validation auto-magically. Rest Framework足够智能,序列化程序将检查模型字段并自动添加唯一的验证。 If you'd rather avoid the unique index on your database then your use of UniqueValidator
is correct I think. 如果您宁愿避免数据库中的唯一索引,那么我认为您对UniqueValidator
的使用是正确的。 BISBN = models.CharField(db_column='BISBN', max_length=10, default=None, unique=True)
Keep in mind that you may be susceptible to race conditions without the unique index on the database. 请记住,如果没有数据库中的唯一索引,您可能会受到竞争条件的影响。 By this I mean that two books could be created/updated to have the same isbn if these operations occur at the same time. 我的意思是,如果这些操作同时发生,那么可以创建/更新两本书以具有相同的isbn。
Meta.unique_together
attribute of the model, ie 同样,我将使用模型的Meta.unique_together
属性对模型上的多个字段应用验证,即 class Book(models.Model):
# fields...
class Meta:
unique_together = ("BNAME", "BISBN")
However if you don't want a unique index on your database for this then your use of the UniqueTogetherValidator
is correct. 但是,如果您不希望在数据库中使用唯一索引,则使用UniqueTogetherValidator
是正确的。
I have another tidbit I think is worth mentioning: 我还有另外一个小窍门,我认为值得一提:
You view should have a lookup_url_kwarg
and lookup_field
to work with the isbn in your url definitions. 您查看应该有一个lookup_url_kwarg
和lookup_field
来处理您的网址定义中的isbn。
class BookViewSet(ModelViewSet):
lookup_url_kwarg = "isbn" # Use the 'isbn' from your url definition
lookup_field = "BISBN" # Use the `BISBN` field on your database/model to perform the lookups
# ...
If you want to handle multiple url kwargs, then you will need to customize the get_queryset()
method. 如果要处理多个url kwargs,则需要自定义get_queryset()
方法。 In the following code I use isbn
to filter the queryset, and then let the view lookup the book by name. 在下面的代码中,我使用isbn
过滤查询集,然后让视图按名称查找书。
class BookViewSet(ModelViewSet):
lookup_url_kwarg = "name"
lookup_field = "BNAME"
def get_queryset(self):
# self.kwargs is a dictionary containing your url kwargs.
isbn = self.kwargs.get("isbn")
book_queryset = super().get_queryset()
return book_queryset.filter(BISBN=isbn)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.