簡體   English   中英

DJango REST框架:如何使用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

所以現在我的問題是:

  1. 例如,如果我沒有在BookViewSet包含def create(self, request) ,我假設當我制作POST /book它什么都不做?
  2. 我正在努力去理解createretrieveupdatedestroy 例如,如果我使用params制作PUT /book/123{ isbn: '123', name: 'test'} ,在def update需要做什么才能從請求中檢索這些數據然后將數據更新到數據庫?
  3. 我想在保存記錄/將其更新到數據庫之前驗證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')

這個對嗎?

  1. 與上一個問題類似,但現在我想確保isbnname一起是唯一的,我認為這是我需要做的:
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')
            )
        ]

這個對嗎?

謝謝

  1. 你的create(self, request, *args, **kwargs)實現什么都不做,因為函數是空的,它甚至不會返回響應。

  2. 您不必在createlistretrieveupdatepartial_updatedestroy放置任何內容,因為您正在使用ModelViewSet類。 ModelViewSet為所有這些提供了默認實現。 如果你真的想保留你的覆蓋,你可以使用這個實現:

def create(self, request, *args, **kwargs):
    """You could add some documentation here"""
    return super().create(request, *args, **kwargs)

我們使用的是super()因為它調用了create的父實現。

  1. 你正在做的是正確的,讓我補充一點,我個人會在模型字段上放置一個unique=True ,而不是將驗證器添加到序列化器中。 Rest Framework足夠智能,序列化程序將檢查模型字段並自動添加唯一的驗證。 如果您寧願避免數據庫中的唯一索引,那么我認為您對UniqueValidator的使用是正確的。

BISBN = models.CharField(db_column='BISBN', max_length=10, default=None, unique=True)

請記住,如果沒有數據庫中的唯一索引,您可能會受到競爭條件的影響。 我的意思是,如果這些操作同時發生,那么可以創建/更新兩本書以具有相同的isbn。

  1. 同樣,我將使用模型的Meta.unique_together屬性對模型上的多個字段應用驗證,即
class Book(models.Model):
    # fields...

    class Meta:
        unique_together = ("BNAME", "BISBN")

但是,如果您不希望在數據庫中使用唯一索引,則使用UniqueTogetherValidator是正確的。

我還有另外一個小竅門,我認為值得一提:

您查看應該有一個lookup_url_kwarglookup_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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM