2

My models.py has 3 fields. One of them is JSONField()

attribute = JSONField(null=True, blank=True)  # Free to add any note to here
type = models.CharField(max_length=30, choices=FileType.choices, default=FileType.zipcode)
file = models.FileField(upload_to='import_files')

I normally set JSONField(null=True, blank=True) for the sake of easiness.

def test_upload_and_process_data_complete_case(self):
    from soken_web.apps.imported_files.models import ImportFile
    with open(str(settings.BASE_DIR) + '/apps/zipcodes/complete.xlsx', 'rb') as uploaded_file:
        data = {
            'attribute': {'author': 'Singh'},
            'type': ImportFile.FileType.zipcode,
            'file': uploaded_file
        }
        response = self.client.post(reverse('api:import_file-list'), data, format='multipart')
        response.render()

        self.assertEqual(status.HTTP_201_CREATED, response.status_code)

And my test runs fine without shooting with JSONField

Experiment:
When I shoot with JSONField like the given. It will failed with this error

AssertionError: Test data contained a dictionary value for key 'attribute', but multipart uploads do not support nested data. You may want to consider using format='json' in this test case.

However, from my understanding I have to post with multipart because of file.

Question:
Is it possible to do unittest shoot the endpoint that has JSONField and FileField in the same time?

Reference:
UnicodeDecodeError: 'utf-8' codec can't decode byte 0xb9 in position 14: invalid start byte

joe
  • 8,383
  • 13
  • 61
  • 109
  • can you just decode the file to a string and then send the object as format=json? What's in the file? – Sam Redway Sep 29 '17 at 15:27
  • is right parser being used ass discused here https://stackoverflow.com/questions/36881771/django-rest-framework-file-upload-causing-an-unsupported-media-type-multipart ? – andilabs Sep 29 '17 at 15:57
  • @SamRedway I have never do that. Thanks for your response. This supposed to be ancient question, but I could not find the solution. – joe Sep 30 '17 at 08:28
  • @andi Let me take time read and digest it for a big moment. – joe Sep 30 '17 at 08:32

1 Answers1

4

After played around with parser.
I found that nothing in the configurations are wrong. Only one thing I missed is. I have to put single quote cover the {"author": "Singh"}.
Because web browser does submit in the str not python object.

def test_upload_and_process_data_complete_case(self):
    from soken_web.apps.imported_files.models import ImportFile
    with open(str(settings.BASE_DIR) + '/apps/zipcodes/complete.xlsx', 'rb') as uploaded_file:
        data = {
            'attribute': '{"author": "Singh"}',
            'type': ImportFile.FileType.zipcode,
            'file': uploaded_file
        }
        response = self.client.post(reverse('api:import_file-list'), data, format='multipart')
        response.render()

        self.assertEqual(status.HTTP_201_CREATED, response.status_code)
joe
  • 8,383
  • 13
  • 61
  • 109
  • Also worth noting that you'll explicitly need single quotes around it (`'{"verbosity": "default"}'` will work, and `"{'verbosity': 'default', }"` will not (will throw something like it wants valid JSON, and single quotes are not allowed in JSON). – benzkji Jun 30 '22 at 12:46