Skip to content
Snippets Groups Projects
Unverified Commit d5690ba5 authored by Nik | Klampfradler's avatar Nik | Klampfradler
Browse files

Include related model fields in syncable_fields

parent abdb1339
No related branches found
No related tags found
No related merge requests found
Pipeline #4595 passed
This commit is part of merge request !396. Comments created here will be created in the context of that merge request.
......@@ -270,13 +270,40 @@ class ExtensibleModel(models.Model, metaclass=_ExtensibleModelBase):
to.property_(_virtual_related, related_name)
@classmethod
def syncable_fields(cls) -> List[models.Field]:
"""Collect all fields that can be synced on a model."""
return [
field
for field in cls._meta.fields
if (field.editable and not field.auto_created and not field.is_relation)
]
def syncable_fields(cls, recursive: bool = True) -> List[models.Field]:
"""Collect all fields that can be synced on a model.
If recursive is True, it recurses into related models and generates virtual
proxy fields to access fields in related models."""
fields = []
for field in cls._meta.fields:
if field.is_relation and recursive:
# Recurse into related model to get its fields as well
for subfield in field.related_model.syncable_fields():
# generate virtual field names for proxy access
name = f"_{field.name}__{subfield.name}"
verbose_name = f"{field.verbose_name} -> {subfield.verbose_name}"
# Add proxy properties to handle access to related model
def getter(self):
if hasattr(self, field.name):
related = getattr(self, field.name)
return getattr(related, subfield.name)
# Related instane does not exist
return None
def setter(self, val):
if hasattr(self, field.name):
related = getattr(self, field.name)
else:
# Auto-create related instance (but do not save)
related = field.related_model()
setattr(related, subfield.name, val)
setattr(cls, name, property(getter, setter))
# Generate a fake field class with enough API to detect attribute names
fields.append(type("FakeRelatedProxyField", (), {"name": name, "verbose_name": verbose_name}))
elif field.editable and not field.auto_created:
fields.append(field)
@classmethod
def syncable_fields_choices(cls) -> Tuple[Tuple[str, str]]:
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment