Opened 5 years ago

Closed 5 years ago

#15054 closed (duplicate)

ContentTypes and proxied models

Reported by: jakedrake Owned by: nobody
Component: Contrib apps Version: 1.2
Severity: Keywords: contentype proxy
Cc: Triage Stage: Unreviewed
Has patch: no Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: UI/UX:

Description

An interesting and useful usage of proxy models and ContentTypes is for implementing the Template Method design pattern. This is a design pattern that others (1 and 2) have discussed as well.

As an example of a template method, a base template model is created, which has its own table, and proxy subclasses implement different behavior, and are stored in the base template table. This is used for abstracting actions on the contents of a model:

class RelationshipAction( Model ):

    content_type = models.ForeignKey(ContentType,editable=False,null=True)

    userA = ForeignKey('User')
    userB = ForeignKey('User')

    def do_something(self, *args, **kwargs):
        pass

class CreateFriendship( RelationshipAction ):
    userA = ForeignKey('User')
    userB = ForeignKey('User')

    class Meta:
        proxy = True

    def do_something(self, *args, **kwargs):
        userA.relationships.add(userB)
        super(CreateFriendship, self).do_something(*args, **kwargs)

However, the base class in this case, RelationshipAction, gets saved as the ContentType instead of CreateFriendship. This is due to the fix committed in changeset #10523 for ticket #10738. This change appears to affect at least one other ticket.

Not having worked in Django source code development for very long, the repercussions and perils of re-enabling this behavior (by reverting changeset #10523) are not clear to me. If this is not a suitable solution, would it be useful to have an addition flag in the Meta class which enables subclass ContentTypes for proxied classes?

thank you in advance.

regards,

JD

Change History (3)

comment:1 Changed 5 years ago by ramiro

  • Needs documentation unset
  • Needs tests unset
  • Patch needs improvement unset

See also #11154 and #14492.

comment:2 Changed 5 years ago by jakedrake

Part of the problem, it would appear, are the differences in philosophies on how a proxy should relate back to a base class. In practice, there are occasions when it is useful to make the proxy equivalent to the base class (ticket #14492), and others (such as this ticket) when the proxy isn't equivalent. Perhaps a good approach would be to have a new Meta flag:

class Derived(base):
    class Meta:
        proxy = True
        proxy_equivalent_to_base = True

If the 'proxy_equivalent_to_base' flag isn't specified or it's set to True, then the default behavior would be to treat them as equivalent in the code--it's current behavior. Otherwise, these will evaluate as different when returning ContentTypes or using the eq operator, and possibly in other places in the code.

comment:3 Changed 5 years ago by russellm

  • Resolution set to duplicate
  • Status changed from new to closed

I'm going to mark this one a duplicate. It isn't exactly the same presentation as #14492 or #11154, but the root cause is the same -- an inconsistency with the understanding of whether a proxy model is the same content type or a different content type. Having another open ticket doesn't help clarify the underlying problem.

I'm loathed to introduce a new meta setting like you describe, but given the widespread usage of Proxy classes (and the conflict in understanding what it means), it may be the only way to resolve the problem.#

Note: See TracTickets for help on using tickets.
Back to Top