[英]How to override the update action in django rest framework ModelViewSet?
[英]DJango REST Framework: How to write Create, List, Update and Delete with ModelViewSet
我還是python / django的新手,目前我正在嘗試使用django rest框架添加REST API。 這是我現在擁有的:
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(模型沒有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
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
所以現在我的問題是:
BookViewSet
包含def create(self, request)
,我假設當我制作POST /book
它什么都不做? create
, retrieve
, update
, destroy
。 例如,如果我使用params制作PUT /book/123
: { isbn: '123', name: 'test'}
,在def update
需要做什么才能從請求中檢索這些數據然后將數據更新到數據庫? isbn
並確保它是唯一的/沒有重復的,我該怎么辦? 我嘗試閱讀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')
這個對嗎?
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')
)
]
這個對嗎?
謝謝
你的create(self, request, *args, **kwargs)
實現什么都不做,因為函數是空的,它甚至不會返回響應。
您不必在create
, list
, retrieve
, update
, partial_update
和destroy
放置任何內容,因為您正在使用ModelViewSet
類。 ModelViewSet
為所有這些提供了默認實現。 如果你真的想保留你的覆蓋,你可以使用這個實現:
def create(self, request, *args, **kwargs):
"""You could add some documentation here"""
return super().create(request, *args, **kwargs)
我們使用的是super()
因為它調用了create
的父實現。
unique=True
,而不是將驗證器添加到序列化器中。 Rest Framework足夠智能,序列化程序將檢查模型字段並自動添加唯一的驗證。 如果您寧願避免數據庫中的唯一索引,那么我認為您對UniqueValidator
的使用是正確的。 BISBN = models.CharField(db_column='BISBN', max_length=10, default=None, unique=True)
請記住,如果沒有數據庫中的唯一索引,您可能會受到競爭條件的影響。 我的意思是,如果這些操作同時發生,那么可以創建/更新兩本書以具有相同的isbn。
Meta.unique_together
屬性對模型上的多個字段應用驗證,即 class Book(models.Model):
# fields...
class Meta:
unique_together = ("BNAME", "BISBN")
但是,如果您不希望在數據庫中使用唯一索引,則使用UniqueTogetherValidator
是正確的。
我還有另外一個小竅門,我認為值得一提:
您查看應該有一個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
# ...
如果要處理多個url kwargs,則需要自定義get_queryset()
方法。 在下面的代碼中,我使用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.