Reputation: 11
I'm creating a Django model that reads from an Oracle SQL database. From the table that the model reads from, some columns have mixed cases and spaces, i.e. "Region" and "Foo Bar". So
SELECT "Region", "Foo Bar" FROM some_table
is perfectly valid on the db side of things. The Django model reads those columns explicitly using the db_column
field,
class SomeModel(models.Model):
region = models.CharField(max_length=100, db_column="Region")
foo_bar = models.CharField(max_length=100, db_column="Foo Bar")
When Django goes to the database, however, I get the error
ORA-00904: invalid identifier: "some_table"."FOO BAR"
from column name being capitalized somewhere along the process. Is there some way that I can force Django to preserve the mixed case from the Django perspective, without modifying the column names on the db side?
I have tried: db_column="'Foo Bar'"
, '"Foo Bar"'
, "\"Foo Bar\""
, none of these seem to make the string interpreted literally and upper-cased.
Thanks! Hacky workarounds welcomed.
Upvotes: 1
Views: 538
Reputation: 2861
When using an Oracle database, Django changes the column names to uppercase (see code).
Solving that is not easy. Your best bet is probably extending the Oracle to override this functionality. To do so you need to make a module for your new backend with a file named base.py
. The contents of which would look like:
from django.db.backends.oracle.base import DatabaseWrapper as OracleWrapper
from django.db.backends.oracle.operations import DatabaseOperations as OracleOperations
class DatabaseOperations(OracleOperations):
def quote_name(self, name):
# Modified version that doesn't apply upper to the quoted column names
if not name.startswith('"') and not name.endswith('"'):
name = '"%s"' % truncate_name(name.upper(), self.max_name_length())
return name.replace('%', '%%')
class DatabaseWrapper(OracleWrapper):
ops_class = DatabaseOperations
DatabaseWrapper
is a special name and you should not change it. After that, you need to set the module as your database engine; you have to go to the parent module (i.e. if the file path is myapp/backends/custom/base.py
you should set it to myapp.backends.custom
).
I haven't got time to properly test this code (I don't actually have an Oracle database to play with) but this is how GIS backends are made, so it should be fairly safe (but it may need some other things).
Upvotes: 2