DJango REST Framework: Как написать Создание, Список, Обновление и Удаление с ModelViewSet - PullRequest
0 голосов
/ 20 мая 2019

Я все еще новичок в python / django, и в настоящее время я пытаюсь добавить REST API, используя django rest framework. Это то, что у меня есть:

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. Если я не включаю def create(self, request) в BookViewSet, например, я предполагаю, что когда я сделаю POST /book, это ничего не даст?
  2. Я изо всех сил пытаюсь понять, что положить внутрь create, retrieve, update, destroy. Например, если я создаю 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. Аналогично предыдущему вопросу, но теперь я хочу убедиться, что и 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')
            )
        ]

Это правильно?

Спасибо

1 Ответ

0 голосов
/ 20 мая 2019
  1. Ваша реализация create(self, request, *args, **kwargs) ничего не сделает, потому что функция пуста, она даже не вернет ответ.

  2. У вас нетположить что-нибудь в 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 в ваших определениях URL.

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-адресов, вам нужно будет настроить метод 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)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...