Я использую Django 2.2.x и djangorestframework 3.11.1.
Внутри ModelViewSet мне пришлось переопределить метод .create(), чтобы настроить поведение по умолчанию.
Иногда мне нужно действительно создать новый экземпляр модели при получении http-запроса POST, иногда мне нужно .update() существующий экземпляр, но все, что я могу получить, это запросы POST (источник — внешний сервер, над которым я не контролирую ). Я знаю, что объединять создание и обновление - плохая идея...
Проблема в том, что всякий раз, когда срабатывает моя логика обновления вместо создания, я получаю следующую ошибку:
AssertionError: Expected view EventViewSet to be called with a URL keyword argument named "pk". Fix your URL conf, or set the `.lookup_field` attribute on the view correctly
Я попробовал два других способа обойти эту проблему:
- напрямую вызывать
Event.objects.update()
, но я понял, что это не подходит для меня, так как я отменил методget_serializer()
, чтобы изменить необработанную полезную нагрузку json, поступающую с внешнего сервера, и я не хочу дублировать здесь логику настройки. - вызов встроенного метода
.update_or_create()
django, но фильтрация была слишком сложной, и у меня все еще та же проблема с первой пулей
Мой взгляд:
class EventViewSet(LoggingMixin, viewsets.ModelViewSet):
"""this is our main api. It allows an event to be created, retrieved, updated and
deleted
"""
def create(self, request, *args, **kwargs):
# first off, we need to find if there is one event NOT closed for the same
# customer, device name and ip address
filters = Q(customer = request.data["Customer"]) & \
~Q(status = "CLOSED") & \
Q(device_name = request.data["DisplayName"]) & \
Q(ip_address = request.data["Address"])
query_set = Event.objects.filter(filters)
if len(query_set) == 1:
# it means there is already an event still NOT closed for that customer/device,
# so we update the existing event
# we need to specify which event we are updating
kwargs["pk"] = str(query_set[0].pk)
return super().update(request, *args, **kwargs)
elif len(query_set) == 0:
# it means there is no open event for that customer/device, hence we need to create it
return super().create(request, *args, **kwargs)
# per our business logic, we should never be here, because there should never be more
# than 1 *open* event for the same customer/device.
else:
pass
Я не знаю, как исправить возвращенное AssertionError
.
Спасибо