Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Django polymorphic compatibility #1357

Open
73VW opened this issue Jun 26, 2024 · 0 comments
Open

Django polymorphic compatibility #1357

73VW opened this issue Jun 26, 2024 · 0 comments

Comments

@73VW
Copy link

73VW commented Jun 26, 2024

Hello everyone,

First of all, let me thank you for this awesome package. It was a real pleasure to use it to track changes in my models.

Problem Statement

I have tried using it with a pair of models that use django-polymorphic and couldn't manage to make it work how I wanted.

Here's a minimal reproducible example of my models:

from polymorphic.models import PolymorphicModel

class BaseStage(PolymorphicModel):
    name = models.CharField(max_length=256)
    display_name = models.CharField(null=True, max_length=256)
    history = HistoricalRecords(inherit=True)


class Company(BaseStage):
    basestage_ptr = models.OneToOneField(
        BaseStage,
        parent_link=True,
        related_name="company_ptr",
        on_delete=models.RESTRICT,
    )

class Stage(BaseStage):
    parent = HistoricForeignKey(BaseStage, on_delete=models.RESTRICT, related_name="children")
    company = models.ForeignKey("Company", on_delete=models.RESTRICT, default=1, related_name="stages")

The goal was to store the hierarchy of a company in a tree.
Our requirements were the following:

  • Root of the tree can only be a company instance
  • Nodes are all linked to their parent and to the company

Describe the solution you'd like

I would have loved to be able to do:

BaseStage.history.filter(Q(Company___pk=company.id) | Q(Stage___company=company))

Just like in django polymorphic.

This would avoid doing something like this:

qs = Stage.history.filter(
    id__in=BaseStage.objects.filter(Q(Company___pk=pk) | Q(Stage___company=pk)).values_list("id", flat=True),
)

dates = qs.values_list("history_date", flat=True)
dates.extend(Company.history.filter(pk=pk).values_list("history_date", flat=True)
 

When one could do:

BaseStage.history.filter(Q(Company___pk=company.id) | Q(Stage___company=company)).values_list("history_date", flat=True)

In order to obtain all the history dates of the whole tree.

Describe alternatives you've considered

I have tried to use Polymorphic as base but couldn't manage to make it work:

class PolymorphicHistoricalRecords(HistoricalRecords):
    def __init__(self, *args, bases=(PolymorphicModel,), **kwargs):
        return super().__init__(*args, bases=bases, **kwargs)

class BaseStage(PolymorphicModel):
    history = PolymorphicHistoricalRecords(inherit=True)
    

It seems that the HistoricXX classes never inherit from PolymorphicModel.

Additional context

I am pretty sure that this would need changes about field naming in either this module or in django polymorphic because django polymorphic needs a polymorphic_ctype column, creating a history on a polymorphic model also generates it and having a polymorphic history on a polymorphic model would require this column twice.

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

No branches or pull requests

1 participant