On 13 avr. 2015, at 20:13, Aymeric Augustin <[email protected]> wrote:
> Replacing adapters is a bit more tricky. Removing them causes the two > regression tests for #17755 to fail. I haven't determined how I can process > parameters passed to QuerySet.raw(), but since that's part of the ORM, I'm > optimistic. Well… I was optimistic :-) I need help. I’m looking for a way to fix https://code.djangoproject.com/ticket/17755 without registering adapters at the level of the DB-API module (sqlite3, MySQLdb, etc.) In a regular QuerySet / Query, a parameter is tied to a field (or equivalent, like an expression, which has an output field). The field's get_db_prep_value method is used to transform the parameter to an appropriate value for the DB-API module. In general, datetime objects are handled by a DateTimeField, whose get_db_prep_value method calls connection.ops.value_to_db_datetime, and everything is fine. Unfortunately, a RawQuerySet / RawQuery cannot use the same logic because its parameters aren't tied to fields. For lack of a better idea, I'm proposing to add a best-effort conversion function to BaseDatabaseOperations: def value_to_db(self, value): """ Transforms a value to something compatible with the backend driver. This method only depends on the type of the value. It's designed for cases where the target type isn't known. As a consequence it may not work perfectly in all circumstances. """ if isinstance(value, datetime.datetime): # must be before date return self.value_to_db_datetime(value) elif isinstance(value, datetime.date): return self.value_to_db_date(value) elif isinstance(value, datetime.time): return self.value_to_db_time(value) elif isinstance(value, decimal.Decimal): return self.value_to_db_decimal(value) else: return value Then I will invoke this method on all parameters, most likely in RawQuery._execute_query. This is the last step in the call chain: Model.objects.raw -> RawQuerySet.__iter__ -> RawQuery.__iter__ -> RawQuery._execute_query -> cursor.execute Does that make sense? I know that I'm duplicating the functionality of database adapters, but I don't have much choice if I don't want to touch the default global adapters. -- Aymeric. -- You received this message because you are subscribed to the Google Groups "Django developers (Contributions to Django itself)" group. To unsubscribe from this group and stop receiving emails from it, send an email to [email protected]. To post to this group, send email to [email protected]. Visit this group at http://groups.google.com/group/django-developers. To view this discussion on the web visit https://groups.google.com/d/msgid/django-developers/D6217D53-6933-43AB-93D9-8B735F1C5FA8%40polytechnique.org. For more options, visit https://groups.google.com/d/optout.
