Code

Opened 7 years ago

Closed 6 years ago

Last modified 3 years ago

#3621 closed (fixed)

FileField in admin broken with sqlite3

Reported by: jimmy@… Owned by: Gulopine
Component: Database layer (models, ORM) Version: master
Severity: Keywords: sqlite3 FileField unique admin, fs-rf-fixed
Cc: Triage Stage: Accepted
Has patch: no Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: UI/UX:

Description (last modified by russellm)

Using the sqlite3 backend:

If FileField has unique=True set, you cannot add a file due to an InterfaceError: Error binding parameter 0 - probably unsupported type.

If you drop the unique=True flag, you are able to insert a object, but not change it; the admin interface gives: Enter a valid filename.

The traceback when unique=True:

Traceback (most recent call last):
File "/Users/jimmy/UNIX/src/django-devel/django/core/handlers/base.py" in get_response
  77. response = callback(request, *callback_args, **callback_kwargs)
File "/Users/jimmy/UNIX/src/django-devel/django/contrib/admin/views/decorators.py" in _checklogin
  55. return view_func(request, *args, **kwargs)
File "/Users/jimmy/UNIX/src/django-devel/django/views/decorators/cache.py" in _wrapped_view_func
  39. response = view_func(request, *args, **kwargs)
File "/Users/jimmy/UNIX/src/django-devel/django/contrib/admin/views/main.py" in add_stage
  250. errors = manipulator.get_validation_errors(new_data)
File "/Users/jimmy/UNIX/src/django-devel/django/db/models/fields/__init__.py" in manipulator_validator_unique
  37. old_obj = self.manager.get(**{lookup_type: field_data})
File "/Users/jimmy/UNIX/src/django-devel/django/db/models/manager.py" in get
  73. return self.get_query_set().get(*args, **kwargs)
File "/Users/jimmy/UNIX/src/django-devel/django/db/models/query.py" in get
  248. obj_list = list(clone)
File "/Users/jimmy/UNIX/src/django-devel/django/db/models/query.py" in __iter__
  108. return iter(self._get_data())
File "/Users/jimmy/UNIX/src/django-devel/django/db/models/query.py" in _get_data
  468. self._result_cache = list(self.iterator())
File "/Users/jimmy/UNIX/src/django-devel/django/db/models/query.py" in iterator
  181. cursor.execute("SELECT " + (self._distinct and "DISTINCT " or "") + ",".join(select) + sql, params)
File "/Users/jimmy/UNIX/src/django-devel/django/db/backends/util.py" in execute
  12. return self.cursor.execute(sql, params)
File "/Users/jimmy/UNIX/src/django-devel/django/db/backends/sqlite3/base.py" in execute
  92. return Database.Cursor.execute(self, query, params)

  InterfaceError at /admin/polls/bar/add/
  Error binding parameter 0 - probably unsupported type.

Attachments (0)

Change History (15)

comment:1 Changed 7 years ago by Gary Wilson <gary.wilson@…>

  • Needs documentation unset
  • Needs tests unset
  • Patch needs improvement unset
  • Triage Stage changed from Unreviewed to Accepted

could an admin please correct the description formatting.

comment:2 Changed 7 years ago by anonymous

This is screwing me up too, I get this error when saving an instance of a model with sqlite3 that has certain fields with default values. Works in the admin but not in my code or the shell

comment:3 Changed 7 years ago by russellm

  • Description modified (diff)

comment:4 Changed 7 years ago by Gulopine

  • Keywords admin, fs-rf added; admin removed

comment:5 Changed 7 years ago by Gulopine

  • Keywords fs-rf-fixed added; fs-rf removed

comment:6 Changed 6 years ago by rwl@…

I'm seeing the same (or similar) behavior running trunk with a sqlite3 backend: I can't save an existing object from the admin interface once I've uploaded a file, whether or not I try to upload a new file.

The error is apparently raised in django/db/models/fields/init.py :

      def isWithinMediaRoot(field_data, all_data):
            f = os.path.abspath(os.path.join(settings.MEDIA_ROOT, field_data))
            if not f.startswith(os.path.abspath(os.path.normpath(settings.MEDIA_ROOT))):
                raise validators.ValidationError, _("Enter a valid filename.")

I've confirmed that the error is raised because field_data contains a leading slash, so that os.path.join(...) returns a path more like the file's URL than its filesystem path; that is, os.path.join(settings.MEDIA_ROOT, field_data) returns a string identical to field_data itself. So, if field_data is "/static/img/ukulele.jpg", then f is "/static/img/ukulele.jpg", instead of, e.g., "/home/mymediaroot/static/img/ukulele.jpg".

I hope that's helpful. I'm not sure exactly why it would be specific to the sqlite3 backend, but I suppose it must have something to do with the way FileField data is translated to the string stored in the database. If someone has suggestions on where to go from here, I'd be happy to look into it further.

comment:7 Changed 6 years ago by Gulopine

  • milestone set to 1.0 beta

comment:8 Changed 6 years ago by felix@…

It happens with MySQL too. You cannot edit or save at all because the file field is always declared illegal once there is something there.

the file name saved has a starting slash:
/releases/verve.jpg

and I guess that it shouldn't

comment:9 Changed 6 years ago by anonymous

I had the same with mysql. the real error was that upload_to='/releases/' was invalid

it failed to save file (and yet did not throw an error)

it threw a false validation error "Please enter a valid filename" - the real problem is the path is invalid which is due to a misconfiguration error.

comment:10 Changed 6 years ago by anonymous

by invalid I meant there should be no slashes before or after

wrong:
upload_to='/releases/'

right:
upload_to='releases'

sorry for multiple posts, Trac threw away ("cookie error") my better written original post.

comment:11 Changed 6 years ago by Gulopine

My apologies for not explaining, but the fs-rf-fixed keyword on this ticket means that my work on #5361 addresses this issue. The plan is to raise a SuspiciousOperation exception if you do this, since you're technically telling Django to save a file somewhere outside your MEDIA_ROOT setting, which will no longer be allowed. It still won't give a validation error when you use manage.py validate, but the error that comes up when you submit a file will be more meaningful.

In the /releases/ example, the error would be:

SuspiciousOperation: Attempted access to '/releases/filename' denied.

comment:12 Changed 6 years ago by jacob

  • Reporter changed from jimmy@… to jimmy@…

Redacted reporter's name by request.

comment:13 Changed 6 years ago by Gulopine

  • Owner changed from nobody to Gulopine
  • Status changed from new to assigned

comment:14 Changed 6 years ago by jacob

  • Resolution set to fixed
  • Status changed from assigned to closed

(In [8244]) File storage refactoring, adding far more flexibility to Django's file handling. The new files.txt document has details of the new features.

This is a backwards-incompatible change; consult BackwardsIncompatibleChanges for details.

Fixes #3567, #3621, #4345, #5361, #5655, #7415.

Many thanks to Marty Alchin who did the vast majority of this work.

comment:11 Changed 3 years ago by jacob

  • milestone 1.0 beta deleted

Milestone 1.0 beta deleted

Add Comment

Modify Ticket

Change Properties
<Author field>
Action
as closed
as The resolution will be set. Next status will be 'closed'
The resolution will be deleted. Next status will be 'new'
Author


E-mail address and user name can be saved in the Preferences.

 
Note: See TracTickets for help on using tickets.