Opened 8 years ago

Closed 8 years ago

Last modified 6 years ago

#5996 closed (fixed)

psycopg2 raises "can't adapt" error where other backends work happily

Reported by: zgoda Owned by: anonymous
Component: Database layer (models, ORM) Version: master
Severity: Keywords:
Cc: Triage Stage: Ready for checkin
Has patch: yes Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: UI/UX:

Description

The description is vague, but I have only vague idea on what's going on. The problem does not manifests itself with sqlite3 and psycopg backends.

I have a model with CharField. Supplying (perfectly valid) unicode object that contains non-ASCII character to this field causes the psycopg2 to raise "Can't adapt" error on saving object. The traceback I get from ipython is like this:

/home/zgoda/www/zgodowie/blog/models.py in save(self)
     42         if not self.slug:
     43             self.slug = slughifi(self.title)
---> 44         super(Label, self).save()
     45
     46

/home/zgoda/www/.python/lib/python2.4/site-packages/django/db/models/base.py in save(self, raw)
    257                 cursor.execute("INSERT INTO %s (%s) VALUES (%s)" % \
    258                     (qn(self._meta.db_table), ','.join(field_names),
--> 259                     ','.join(placeholders)), db_values)
    260             else:
    261                 # Create a new record with defaults for everything.

ProgrammingError: can't adapt 

It does not matter if I do a force_unicode() on slughifi() output, the error is the same.

The definition for the model is as follows:

class Label(models.Model):
    title = models.CharField(max_length=80, unique=True)
    slug = models.CharField(max_length=80, editable=False)
    description = models.TextField(null=True, blank=True)

    def save(self):
        if not self.slug:
            self.slug = slughifi(self.title)
        super(Label, self).save()

Attachments (1)

pg_safeunicode.diff (1.3 KB) - added by remco@… 8 years ago.
Unit test + fix

Download all attachments as: .zip

Change History (9)

comment:1 Changed 8 years ago by zgoda

  • Needs documentation unset
  • Needs tests unset
  • Patch needs improvement unset

Versions of libraries involved

In [2]: psycopg2.__version__
Out[2]: '2.0.6 (dec dt ext pq3)'

In [4]: psycopg.__version__
Out[4]: '1.1.21'

comment:2 Changed 8 years ago by sacrebis@…

I think I have the same problem, but it is related to SafeString and SafeUnicode objects.

In my case I have inclusion tag which accepts string as second argument.

{% some_inclusion_tag some_value %}

Inclusion tag code:

@inclusion_tag....
def some_inclusion_tag(value):
    obj = Klass.object.get(value=value)

and this raises "Can't adapt" error.

But look at that:

>>>  type(value)
<class 'django.utils.safestring.SafeUnicode'>

Could you check type of "self.title" ?

comment:3 Changed 8 years ago by zgoda

The title value is ordinary unicode object, but the slug value is SafeUnicode. It looks like psycopg2 backend is unable to convert SafeUnicode to ordinary unicode object (calling unicode() does the trick).

comment:4 Changed 8 years ago by remco@…

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

comment:5 Changed 8 years ago by remco@…

  • Triage Stage changed from Unreviewed to Accepted

We have looked at the issue as part of the 01-dec sprint. The issue is psycopg2 specific. Psycopg2 is indeed not able to adapt the SafeUnicode field even though SafeUnicode is a subclass of unicode. We are thinking about adding a psycopg adapter for the SafeUnicode type in the psycopg2 backend as proposed here: http://www.initd.org/tracker/psycopg/wiki/psycopg2_documentation#adaptation-of-python-values-to-sql-types

Unit tests + patch will be added soon

comment:6 Changed 8 years ago by remco@…

  • Has patch set
  • Triage Stage changed from Accepted to Ready for checkin

Fixed by adding a field test for saving a SafeUnicode object in a model and patching the psycopg2 backend.

See attached patch for both unit test and fix.

Changed 8 years ago by remco@…

Unit test + fix

comment:7 Changed 8 years ago by mtredinnick

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

(In [6816]) Fixed #5996 -- Add a pyscopg2 convertor for SafeUnicode -> unicode. Thanks, remco@…

comment:8 Changed 6 years ago by anibal

FYI:
I had recently a can't adapt error in a FooModel.objects.get(..., user=request.user) line

And the issue was fixed changing the line ... user__id=request.user.id

Now I don't receive "can't adapt" mails from production server any more.

Note: See TracTickets for help on using tickets.
Back to Top