1

I have a view that should generate a temporary JSON file and save this TempFile to the database. The content to this file, a dictionary named assets, is created using DRF using serializers. This file should be written to the database in a model called CollectionSnapshot.

class CollectionSnapshotCreate(generics.CreateAPIView):
    permission_classes = [MemberPermission, ]

    def create(self, request, *args, **kwargs):
        collection = get_collection(request.data['collection_id'])
        items = Item.objects.filter(collection=collection)

        assets = {
            "collection": CollectionSerializer(collection, many=False).data,
            "items": ItemSerializer(items, many=True).data,
        }

        fp = tempfile.TemporaryFile(mode="w+")
        json.dump(assets, fp)
        fp.flush()

        CollectionSnapshot.objects.create(
            final=False,
            created_by=request.user,
            collection_id=collection.id,
            file=ContentFile(fp.read(), name="assets.json")
        )
        fp.close()

        return JsonResponse({}, status=200)

Printing assets returns the dictionary correctly. So I am getting the dictionary normally.

Following the solution below I do get the file saved to the db, but without any content: copy file from one model to another

Seems that json.dump(assets, fp) is failing silently, or I am missing something to actually save the content to the temp file prior to sending it to the database.

The question is: why is the files in the db empty?

1 Answers1

1

I found out that fp.read() throws content based on the current pointer in the file. At least, that is my understanding. So after I dump assets dict as json the to temp file, I have to bring back the cursor to the beggining using fp.seek(0). This way, when I call fp.read() inside file=ContentFile(fp.read(), ...) it actually reads all the content. It was giving me empty because there was nothing to read since the cursor was at the end of the file.

    fp = tempfile.TemporaryFile(mode="w+")
    json.dump(assets, fp)
    fp.flush()
    fp.seek(0) // important

    CollectionSnapshot.objects.create // stays the same