简体   繁体   中英

How to write to Django FileField from a tempfile?

I am processing an image within a Django app. I used rasterio to process the geospatial image. I want to save the output directly to a FileField in a Model. I used a tempfile to write the output from rasterio, and used the method Model.FileField.save to hopefully write it with a reference to my Model instance.

I have a simple model:

class MaskedLayer(models.Model):
    name = models.CharField(max_length=250, blank=True)
    file = models.FileField(
        upload_to='masked',
        null=True,
        max_length=500)

In my tasks, however this is an example:

from celery import shared_task
import rasterio
import tempfile

from app.models import MaskedLayer


@shared_task
def process_image():

    mask_layer_name = 'processed_image.tif'
    masked_layer = MaskedLayer.objects.create()

    with rasterio.open('example.tif') as dataset: # only example of reading/processing of image
        out_image = dataset.read()

    with tempfile.NamedTemporaryFile() as tmpfile:
        tmpfile.write(out_image)

        with rasterio.open(tmpfile.name) as dataset:
            masked_layer.file.save(mask_layer_name, File(dataset))


    pass

I get this response. I am not sure of the error. Feel free to use the example file .

Fatal Python error: Segmentation fault

Current thread 0x00007f453b463740 (most recent call first): File "/usr/local/lib/python3.11/site-packages/django/views/debug.py", line 232 in get_traceback_frame_variables File "/usr/local/lib/python3.11/site-packages/django/views/debug.py", line 544 in get_exception_traceback_frames File "/usr/local/lib/python3.11/site-packages/django/views/debug.py", line 490 in get_traceback_frames File "/usr/local/lib/python3.11/site-packages/django/views/debug.py", line 320 in get_traceback_data File "/usr/local/lib/python3.11/site-packages/django/views/debug.py", line 403 in get_traceback_text File "/usr/local/lib/python3.11/site-packages/django/utils/log.py", line 125 in emit File "/usr/local/lib/python3.11/logging/ init .py", line 978 in handle File "/usr/local/lib/python3.11/logging/ init .py", line 1706 in callHandlers File "/usr/local/lib/python3.11/logging/ init .py", line 1644 in handle File "/usr/local/lib/python3.11/logging/ init .py", line 1634 in _log
File "/usr/local/lib/python3.11/logging/ init .py", line 1518 in error File "/usr/local/lib/python3.11/site-packages/django/utils/log.py", line 241 in log_response File "/usr/local/lib/python3.11/site-packages/django/core/handlers/exception.py", line 143 in response_for_exception File "/usr/local/lib/python3.11/site-packages/django/core/handlers/exception.py", line 57 in inner File "/usr/local/lib/python3.11/site-packages/django/utils/deprecation.py", line 136 in call File "/usr/local/lib/python3.11/site-packages/django/core/handlers/exception.py", line 55 in inner File "/usr/local/lib/python3.11/site-packages/django/utils/deprecation.py", line 136 in call File "/usr/local/lib/python3.11/site-packages/django/core/handlers/exception.py", line 55 in inner File "/usr/local/lib/python3.11/site-packages/django/utils/deprecation.py", line 136 in call File "/usr/local/lib/python3.11/site-packages/django/core/handlers/exception.py", line 55 in inner File "/usr/local/lib/python3.11/site-packages/django/utils/deprecation.py", line 136 in call File "/usr/local/lib/python3.11/site-packages/django/core/handlers/exception.py", line 55 in inner File "/usr/local/lib/python3.11/site-packages/django/utils/deprecation.py", line 136 in call File "/usr/local/lib/python3.11/site-packages/django/core/handlers/exception.py", line 55 in inner File "/usr/local/lib/python3.11/site-packages/django/utils/deprecation.py", line 136 in call File "/usr/local/lib/python3.11/site-packages/django/core/handlers/exception.py", line 55 in inner File "/usr/local/lib/python3.11/site-packages/django/utils/deprecation.py", line 136 in call File "/usr/local/lib/python3.11/site-packages/django/core/handlers/exception.py", line 55 in inner File "/usr/local/lib/python3.11/site-packages/django/core/handlers/base.py", line 140 in get_response File "/usr/local/lib/python3.11/site-packages/rest_framework/test.py", line 258 in get_response File "/usr/local/lib/python3.11/site-packages/django/test/client.py", line 153 in call File "/usr/local/lib/python3.11/site-packages/django/test/client.py", line 805 in request File "/usr/local/lib/python3.11/site-packages/rest_framework/test.py", line 238 in request File "/usr/local/lib/python3.11/site-packages/rest_framework/test.py", line 286 in request File "/usr/local/lib/python3.11/site-packages/django/test/client.py", line 541 in generic File "/usr/local/lib/python3.11/site-packages/rest_framework/test.py", line 234 in generic File "/usr/local/lib/python3.11/site-packages/rest_framework/test.py", line 210 in post File "/usr/local/lib/python3.11/site-packages/rest_framework/test.py", line 296 in post File "/usr/src/app/data_management/tests/test_data_management.py", line 18 in test_solar_pot File "/usr/local/lib/python3.11/unittest/case.py", line 579 in _callTestMethod File "/usr/local/lib/python3.11/unittest/case.py", line 623 in run File "/usr/local/lib/python3.11/unittest/case.py", line 678 in call
File "/usr/local/lib/python3.11/site-packages/django/test/testcases.py", line 416 in _setup_and_call File "/usr/local/lib/python3.11/site-packages/django/test/testcases.py", line 381 in call File "/usr/local/lib/python3.11/unittest/suite.py", line 122 in run File "/usr/local/lib/python3.11/unittest/suite.py", line 84 in call
File "/usr/local/lib/python3.11/unittest/runner.py", line 217 in run
File "/usr/local/lib/python3.11/site-packages/django/test/runner.py", line 980 in run_suite File "/usr/local/lib/python3.11/site-packages/django/test/runner.py", line 1058 in run_tests File "/usr/local/lib/python3.11/site-packages/django/core/management/commands/test.py", line 68 in handle File "/usr/local/lib/python3.11/site-packages/django/core/management/base.py", line 448 in execute File "/usr/local/lib/python3.11/site-packages/django/core/management/base.py", line 402 in run_from_argv File "/usr/local/lib/python3.11/site-packages/django/core/management/commands/test.py", line 24 in run_from_argv File "/usr/local/lib/python3.11/site-packages/django/core/management/ init .py", line 440 in execute File "/usr/local/lib/python3.11/site-packages/django/core/management/ init .py", line 446 in execute_from_command_line File "/usr/src/app/manage.py", line 18 in main File "/usr/src/app/manage.py", line 22 in

Extension modules: psycopg2._psycopg, numpy.core._multiarray_umath, numpy.core._multiarray_tests, numpy.linalg._umath_linalg, numpy.fft._pocketfft_internal, numpy.random._common, numpy.random.bit_generator, numpy.random._bounded_integers, numpy.random._mt19937, numpy.random.mtrand, numpy.random._philox, numpy.random._pcg64, numpy.random._sfc64, numpy.random._generator, rasterio._version, rasterio._err, rasterio._filepath, rasterio._env, rasterio._transform, rasterio._base, rasterio.crs, rasterio._features, rasterio._warp, rasterio._io, fiona._err, fiona._geometry, fiona._shim, fiona._env, fiona.schema, fiona.ogrext, fiona._crs (total: 31)

I am by far not familiar with rasterio and celery but let me show you my working implementation as guidance:

import io
from django.core.files.images import ImageFile

def _upload_location(instance, filename):
    return f'/some/path/{filename}'

class MyModel(models.Model):
    model_image_field = models.ImageField(null=True, blank=True, upload_to=_upload_location, editable=False)

    def save_structure_img(self):
        tmp_img = io.BytesIO()  # create buffer
        structure_img = self.create_structure_img() # create img 
        structure_img.save(tmp_img, 'PNG')  # utilize save method of your image to save it to the buffer
        name = "your_wanted_filename"  # create a name
        self.model_image_field.save(f'{name}.png', ImageFile(tmp_img)) # save buffer to model_image field

I know, I edited out the creation of structure_img but that should not matter, because it is specific to my project.

Let me try to translate this to your usecase:

import io
from django.core.files.images import ImageFile

@shared_task
def process_image():

    mask_layer_name = 'processed_image.tif'
    masked_layer = MaskedLayer.objects.create()

    with rasterio.open('example.tif') as dataset: # only example of reading/processing of image
        out_image = dataset.read()
    
    tmp_img = io.BytesIO() # create buffer
    out_image.save(tmp_img, 'PNG')
    # i hope this is the right place where out_image has a `.save` method.
    name = "your_wanted_filename"
    
    masked_layer.field.save(f'{name}.png', ImageFile(tmp_img))
    pass

Also I admit that I have no clue what your proposed error is trying to tell me. But I feel like the database is complaining about what you are trying to insert. If you so search for an answer how to fix exactly that error, my answer is not what you are looking for. It is more of an alternative approach to the same solution.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM