Skip to content

Conversation

WaVEV
Copy link
Collaborator

@WaVEV WaVEV commented Aug 25, 2025

Index are defined with __ for EMF

class Address(EmbeddedModel):
    unique_constraint_one = models.CharField(max_length=10)
    
    class Meta:
        app_label = "schema_"

class Author(EmbeddedModel):
    address = EmbeddedModelField(Address)
    unique_constraint_two = models.CharField(max_length=10)

    class Meta:
        app_label = "schema_"

class Book(models.Model):
    author = EmbeddedModelField(Author)

    class Meta:
        app_label = "schema_"
        constraints = [
            models.UniqueConstraint(
                fields=["author.unique_constraint_two"],
                name="unique_two",
            ),
            models.UniqueConstraint(
                fields=["author.address.unique_constraint_one"],
                name="unique_one",
            ),
        ]

@WaVEV WaVEV force-pushed the INTPYTHON-698-Define-indexes-on-Embedded-Models-in-Top-Level-Model branch from 998a080 to 5dd116b Compare August 25, 2025 03:05
Comment on lines 188 to 197
# Remove the top level indexes.
# TODO: Find a workaround
for index in model._meta.indexes:
if any(
field_name.startswith(f"{field.column}{LOOKUP_SEP}")
for field_name in index.fields
):
self.remove_index(model, index)
for constraint in model._meta.constraints:
if any(
field_name.startswith(f"{field.column}{LOOKUP_SEP}")
for field_name in constraint.fields
):
self.get_collection(model._meta.db_table).drop_index(constraint.name)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would think this is unnecessary since the Index/Constraint would have to be removed from the model's Meta.indexes/constraints before removing the field.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤔 Oki, I will try to move the logic into _remove_model_indexes and _remove_field_unique. The downfall is I have to pass all the indexes from its parents. Like concatenating all way down the recursion. The index could have been created in anywhere of the hierarchy.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it's simpler than you describe. Example:

class Book(models.Model):
    author = EmbeddedModelField(Author)

    class Meta:
        app_label = "schema_"
        indexes = [
            models.Index(fields=["author__indexed_two"]),
            models.Index(fields=["author__address__indexed_one"]),
        ]

I removing the an index, the generated migration operation is:

migrations.RemoveIndex(
    model_name='book',
    name='embed_index_author._f84329_idx',
),

The logic you describe isn't needed.

Comment on lines 127 to 144
class Options(base.Options):
def get_field(self, field_name):
if LOOKUP_SEP in field_name:
previous = self
keys = field_name.split(LOOKUP_SEP)
path = []
for field in keys:
field = base.Options.get_field(previous, field)
if isinstance(field, EmbeddedModelField):
previous = field.embedded_model._meta
else:
previous = field
path.append(field.column)
column = ".".join(path)
embedded_column = field.clone()
embedded_column.column = column
return embedded_column
return super().get_field(field_name)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Monkey patching at such a low level seems risky, though I haven't much about what could go wrong. Instead I imagined an Index subclass with this sort of logic. Did you consider it?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤔 Maybe is feasible if we create something like EMFIndex. I didn't considered yet. I could take a look.

Copy link
Collaborator Author

@WaVEV WaVEV Aug 26, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

mmh this way (monkey patching) will not work, I forgot that foreign field, lookups and many other things use this. So isn't very straightforward. I have to think another way to solve this

@WaVEV WaVEV force-pushed the INTPYTHON-698-Define-indexes-on-Embedded-Models-in-Top-Level-Model branch from 3e722d1 to 2010776 Compare August 25, 2025 23:16
@timgraham timgraham changed the title Intpython 698 define indexes on embedded models in top level model INTPYTHON-698 Allow defining embedded model indexes on the top-level model Aug 26, 2025
@WaVEV WaVEV force-pushed the INTPYTHON-698-Define-indexes-on-Embedded-Models-in-Top-Level-Model branch 2 times, most recently from 369e6b5 to d5b415d Compare August 30, 2025 23:06
@WaVEV WaVEV force-pushed the INTPYTHON-698-Define-indexes-on-Embedded-Models-in-Top-Level-Model branch from d5b415d to a775af8 Compare August 30, 2025 23:42
@WaVEV WaVEV force-pushed the INTPYTHON-698-Define-indexes-on-Embedded-Models-in-Top-Level-Model branch from f70d0f6 to 32a1712 Compare August 31, 2025 13:46
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants