Reputation: 1980
I am trying to do bulkinsert and bulk update in single request using https://github.com/miki725/django-rest-framework-bulk, Below is my list serilizer and modelViewset.
class BookListSerializer(serializers.ListSerializer):
def update(self, instance, validated_data):
# Maps for id->instance and id->data item.
book_mapping = {book.id: book for book in instance}
data_mapping = {item['id']: item for item in validated_data}
# Perform creations and updates.
ret = []
for book_id, data in data_mapping.items():
book = book_mapping.get(book_id, None)
if book is None:
ret.append(self.child.create(data))
else:
ret.append(self.child.update(book, data))
# Perform deletions.
for book_id, book in book_mapping.items():
if book_id not in data_mapping:
book.delete()
return ret
class BookSerializer(serializers.Serializer):
class Meta:
list_serializer_class = BookListSerializer
class BookCSVViewSet(generics.BulkModelViewSet):
queryset = Book.objects.all()
serializer_class = BookCSVSerializer
def get_serializer(self, *args, **kwargs):
if "data" in kwargs:
data = kwargs["data"]
if isinstance(data, list):
kwargs["many"] = True
return super(BookCSVViewSet, self).get_serializer(*args, **kwargs)
@list_route(methods=['PUT'])
def bulk_update(self, request, *args, **kwargs):
partial = kwargs.pop('partial', False)
# restrict the update to the filtered queryset
serializer = self.get_serializer(
self.filter_queryset(self.get_queryset()),
data=request.data,
many=True,
partial=partial,
)
validated_data = []
validation_errors = []
for item in request.data:
print self.get_queryset().get(pk=item['id'])
item_serializer = self.get_serializer(
self.get_queryset().get(pk=item['id']),
data=item,
partial=partial,
)
item_serializer.is_valid(raise_exception=True)
if item_serializer.errors:
validation_errors.append(item_serializer.errors)
validated_data.append(item_serializer.validated_data)
if validation_errors:
raise ValidationError(validation_errors)
serializer._validated_data = validated_data
self.perform_bulk_update(serializer)
return Response(serializer.data, status=status.HTTP_200_OK)
I am sending both existing record and new record in the same HTTP request,
[{id:23, name:"bob", book:"hello"},{id:"299, name:"bob", book:"hello"}]
id:23 is an existing record and id:299 is an new record,for old record it looks fine, however when new record is there above code fails at below line of code, by saying matching query does not exist
self.get_queryset().get(pk=item['id'])
please guide how can approach bulk update and create in single request or any other approach.
Upvotes: 0
Views: 1089
Reputation: 1450
In my opinion, you can try 'filter' instead of using 'get'. If found, it can update. If not found, we can create. May be like this:
for item in request.data:
current_item = self.get_queryset().filter(pk=item['id'])
if current_item:
item_serializer = self.get_serializer(current_item.first(),
data=item,
partial=partial,
)
else:
new_book = Book.objects.create(name=item['name'], book=item['book'])
item_serializer = self.get_serializer(new_book)
item_serializer.is_valid(raise_exception=True)
if item_serializer.errors:
validation_errors.append(item_serializer.errors)
validated_data.append(item_serializer.validated_data)
Hoop this help :v
Upvotes: 1