This branch is an experiment, and it's currently broken.
I mentioned this in #8:
My theory is that a composite type is similar to a model; so, it should be possible to make Django think that it is a Model, and hack into Django so that it generates the types and selects them correctly.
Success 1: By subclassing CreateModel migration operation into a CreateType operation, I've been able to create composite types without issues. However, the migration generated by makemigrations needs hand editing as there is no way to tell it to use that particular operation instead of the CreateModel operation, which is hardcoded. This is easily fixed in Django.
Success 2: I've renamed db_type to db_table, making the composite type compatible with Model. This has so far removed quite a bit of hacky code.
Fail 1: Models absolutely require a primary key in Django. I have however worked around this by generating a dummy __id column, which I ignore during field generation. I believe this will be a huge blocker for this approach if the code is upstreamed into Django itself.
So this is where I'm at. The two main changes are db_type is now db_table (and this is still required; breaking change), and _meta.fields is now the same structure as for normal fields, which is a list of field instances; their name comes from field.name.
I've had to use a custom manager that always returns empty querysets, as the tests surfaced that some django code (such as the db serialization code) will query all models. Types should always be empty for this.
This doesn't solve #8 because something like AlterType hasn't been implemented, but it makes it a lot easier to tackle.
Also, because I replaced the migration operation with one that doesn't rely on the class itself, I have had to drop support for the composite_type_created signal. IMO this is not a useful signal anyway - any push back?
Currently, I'm fighting with the following test error:
> self.assertIn(expected_deconstruction, text)
E AssertionError: 'base_field=tests.models.Card.Field()' not found in 'django.contrib.postgres.fields.ArrayField(base_field=postgres_composite_types.composite_type.Card.Field(), size=None)'
Migrations generate invalid imports. This is not fixable in current Django due to the migration autodetector not having a concept of non-top-level attributes of a module.
Migrations generate CreateModel instead of CreateType instruction. This is not fixable in current Django, but the CreateModel can be swapped out 1:1 with a CreateType
Migrations include an _id_not_used dummy field upon generation. This can safely be removed or left in, it will be ignored regardless.
Migration options include base_manager_name and default_manager_name. This is fixable, but harmless, and I've spent enough time on getting this hack to work :P
This branch is an experiment, and it's currently broken.
I mentioned this in #8:
So this is where I'm at. The two main changes are
db_type
is nowdb_table
(and this is still required; breaking change), and_meta.fields
is now the same structure as for normal fields, which is a list of field instances; their name comes from field.name.I've had to use a custom manager that always returns empty querysets, as the tests surfaced that some django code (such as the db serialization code) will query all models. Types should always be empty for this.
This doesn't solve #8 because something like AlterType hasn't been implemented, but it makes it a lot easier to tackle.
Also, because I replaced the migration operation with one that doesn't rely on the class itself, I have had to drop support for the
composite_type_created
signal. IMO this is not a useful signal anyway - any push back?Currently, I'm fighting with the following test error:
I'm still investigating what's happening here.