简体   繁体   中英

TypeError when saving a Django model that contains an ImageField

I have a basic model for which I've added an ImageField .

class Category(models.Model):
    name = models.CharField(max_length=200, unique=True)
    slug = models.SlugField(blank=True, editable=False)
    image = models.ImageField(upload_to='images', blank=True)

    def __str__(self):
        """
            Field to show in the related models admin site.
        """
        return self.name

    class Meta:
        # order of drop-down list items
        ordering = ('name',)

        # plural form in admin view
        verbose_name_plural = 'categories'

    def save(self, *args, **kwargs):
        """
            Save slug when saving model.
            Slug saved only if not existant, to avoid duplicity of urls.
        """
        if not self.id:
            # new object to create
            self.slug = slugify(self.name)[:50]

        super().save(*args, **kwargs)

When I try to create/update an item from the admin section by setting an image in the ImageField , I get the following error (this error doesn't appear when the ImageField isn't set):

Internal Server Error: /admin/app/category/8/change/
Traceback (most recent call last):
  File "/usr/lib/python3.6/site-packages/django/core/handlers/exception.py", line 39, in inner
    response = get_response(request)
  File "/usr/lib/python3.6/site-packages/django/core/handlers/base.py", line 187, in _get_response
    response = self.process_exception_by_middleware(e, request)
  File "/usr/lib/python3.6/site-packages/django/core/handlers/base.py", line 185, in _get_response
    response = wrapped_callback(request, *callback_args, **callback_kwargs)
  File "/usr/lib/python3.6/site-packages/django/contrib/admin/options.py", line 544, in wrapper
    return self.admin_site.admin_view(view)(*args, **kwargs)
  File "/usr/lib/python3.6/site-packages/django/utils/decorators.py", line 149, in _wrapped_view
    response = view_func(request, *args, **kwargs)
  File "/usr/lib/python3.6/site-packages/django/views/decorators/cache.py", line 57, in _wrapped_view_func
    response = view_func(request, *args, **kwargs)
  File "/usr/lib/python3.6/site-packages/django/contrib/admin/sites.py", line 211, in inner
    return view(request, *args, **kwargs)
  File "/usr/lib/python3.6/site-packages/django/contrib/admin/options.py", line 1512, in change_view
    return self.changeform_view(request, object_id, form_url, extra_context)
  File "/usr/lib/python3.6/site-packages/django/utils/decorators.py", line 67, in _wrapper
    return bound_func(*args, **kwargs)
  File "/usr/lib/python3.6/site-packages/django/utils/decorators.py", line 149, in _wrapped_view
    response = view_func(request, *args, **kwargs)
  File "/usr/lib/python3.6/site-packages/django/utils/decorators.py", line 63, in bound_func
    return func.__get__(self, type(self))(*args2, **kwargs2)
  File "/usr/lib/python3.6/contextlib.py", line 53, in inner
    return func(*args, **kwds)
  File "/usr/lib/python3.6/site-packages/django/contrib/admin/options.py", line 1449, in changeform_view
    self.save_model(request, new_object, form, not add)
  File "/usr/lib/python3.6/site-packages/django/contrib/admin/options.py", line 1007, in save_model
    obj.save()
  File "/home/hakim/project/app/models.py", line 103, in save
    super().save(*args, **kwargs)
  File "/usr/lib/python3.6/site-packages/django/db/models/base.py", line 796, in save
    force_update=force_update, update_fields=update_fields)
  File "/usr/lib/python3.6/site-packages/django/db/models/base.py", line 824, in save_base
    updated = self._save_table(raw, cls, force_insert, force_update, using, update_fields)
  File "/usr/lib/python3.6/site-packages/django/db/models/base.py", line 886, in _save_table
    for f in non_pks]
  File "/usr/lib/python3.6/site-packages/django/db/models/base.py", line 886, in <listcomp>
    for f in non_pks]
  File "/usr/lib/python3.6/site-packages/django/db/models/fields/files.py", line 292, in pre_save
    file.save(file.name, file, save=False)
  File "/usr/lib/python3.6/site-packages/django/db/models/fields/files.py", line 91, in save
    self.name = self.storage.save(name, content, max_length=self.field.max_length)
  File "/usr/lib/python3.6/site-packages/django/core/files/storage.py", line 53, in save
    name = self.get_available_name(name, max_length=max_length)
  File "/usr/lib/python3.6/site-packages/django/core/files/storage.py", line 77, in get_available_name
    while self.exists(name) or (max_length and len(name) > max_length):
  File "/usr/lib/python3.6/site-packages/django/core/files/storage.py", line 394, in exists
    return os.path.exists(self.path(name))
  File "/usr/lib/python3.6/site-packages/django/core/files/storage.py", line 407, in path
    return safe_join(self.location, name)
  File "/usr/lib/python3.6/site-packages/django/utils/functional.py", line 35, in __get__
    res = instance.__dict__[self.name] = self.func(instance)
  File "/usr/lib/python3.6/site-packages/django/core/files/storage.py", line 283, in location
    return abspathu(self.base_location)
  File "/usr/lib/python3.6/posixpath.py", line 369, in abspath
    path = os.fspath(path)
TypeError: expected str, bytes or os.PathLike object, not tuple

And the relevant part of settings.py :

# Location of uploaded images

MEDIA_ROOT = os.path.join(BASE_DIR, 'media'),


# URL of uploaded images

MEDIA_URL = '/media/'

The error indicates the problem is a tuple being present instead of a string in the following line, where path is the location to upload the file:

path = os.fspath(path)

Since upload_to is correctly set to a string in the model, I figured the problem might be related to MEDIA_ROOT , which turned out to be a tuple (as clarified in comments). Making it a string solved the problem.

By this error:

TypeError: expected str, bytes or os.PathLike object, not tuple

I think the error is in the image field of the form. In save() do the first:

print(self.image)

To see what you are saving, it will be a tuple instead of an string.

In my case I had it like this:

MEDIA_ROOT=[os.path.join(BASE_DIR,'media')]

Writing it this way solved the error:

MEDIA_ROOT=os.path.join(BASE_DIR,'media')

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