-
Notifications
You must be signed in to change notification settings - Fork 46
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Due to limitations of Django the schema must only have the `default` module. Also all link properties and multi properties are forbidden since they produce models without a unique `id` (or other primary key) column. Django cannot properly handle updates to that. Added tests for the generated Django models.
- Loading branch information
1 parent
ca4cfb2
commit ba850f1
Showing
15 changed files
with
1,075 additions
and
77 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
import unittest | ||
|
||
# No tests here, but we want to skip the unittest loader from attempting to | ||
# import ORM packages which may not have been installed (like Django that has | ||
# a few custom adjustments to make our models work). | ||
def load_tests(loader, tests, pattern): | ||
return tests |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
import django | ||
|
||
__version__ = "0.0.1" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
from django.apps import AppConfig | ||
|
||
|
||
class GelPGModel(AppConfig): | ||
name = "gel.orm.django.gelmodels" | ||
|
||
def ready(self): | ||
from django.db import connections, utils | ||
|
||
gel_compiler_module = "gel.orm.django.gelmodels.compiler" | ||
|
||
# Change the current compiler_module | ||
for c in connections: | ||
connections[c].ops.compiler_module = gel_compiler_module | ||
|
||
# Update the load_backend to use our DatabaseWrapper | ||
orig_load_backend = utils.load_backend | ||
|
||
def custom_load_backend(*args, **kwargs): | ||
backend = orig_load_backend(*args, **kwargs) | ||
|
||
class GelPGBackend: | ||
@staticmethod | ||
def DatabaseWrapper(*args2, **kwargs2): | ||
connection = backend.DatabaseWrapper(*args2, **kwargs2) | ||
connection.ops.compiler_module = gel_compiler_module | ||
return connection | ||
|
||
return GelPGBackend | ||
|
||
utils.load_backend = custom_load_backend |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
from django.db.models.sql.compiler import ( # noqa | ||
SQLAggregateCompiler, | ||
SQLCompiler, | ||
SQLDeleteCompiler, | ||
) | ||
from django.db.models.sql.compiler import ( # noqa | ||
SQLInsertCompiler as BaseSQLInsertCompiler, | ||
) | ||
from django.db.models.sql.compiler import ( # noqa | ||
SQLUpdateCompiler as BaseSQLUpdateCompiler, | ||
) | ||
|
||
|
||
class GelSQLCompilerMixin: | ||
''' | ||
The reflected models have two special fields: `id` and `obj_type`. Both of | ||
those fields should be read-only as they are populated automatically by | ||
Gel and must not be modified. | ||
''' | ||
@property | ||
def readonly_gel_fields(self): | ||
try: | ||
# Verify that this is a Gel model reflected via Postgres protocol. | ||
gel_pg_meta = getattr(self.query.model, "GelPGMeta") | ||
except AttributeError: | ||
return set() | ||
else: | ||
return {'id', 'gel_type_id'} | ||
|
||
def as_sql(self): | ||
readonly_gel_fields = self.readonly_gel_fields | ||
if readonly_gel_fields: | ||
self.remove_readonly_gel_fields(readonly_gel_fields) | ||
return super().as_sql() | ||
|
||
|
||
class SQLUpdateCompiler(GelSQLCompilerMixin, BaseSQLUpdateCompiler): | ||
def remove_readonly_gel_fields(self, names): | ||
''' | ||
Remove the values corresponding to the read-only fields. | ||
''' | ||
values = self.query.values | ||
# The tuple is (field, model, value) | ||
values[:] = (tup for tup in values if tup[0].name not in names) | ||
|
||
|
||
class SQLInsertCompiler(GelSQLCompilerMixin, BaseSQLInsertCompiler): | ||
def remove_readonly_gel_fields(self, names): | ||
''' | ||
Remove the read-only fields. | ||
''' | ||
fields = self.query.fields | ||
|
||
try: | ||
fields[:] = (f for f in fields if f.name not in names) | ||
except AttributeError: | ||
# When deserializing, we might get an attribute error because this | ||
# list shoud be copied first: | ||
# | ||
# "AttributeError: The return type of 'local_concrete_fields' | ||
# should never be mutated. If you want to manipulate this list for | ||
# your own use, make a copy first." | ||
|
||
self.query.fields = [f for f in fields if f.name not in names] |
Oops, something went wrong.