Skip to content

How to use abstract base model classes with intermediate abstract classes #366

@specialorange

Description

@specialorange

Problem (help wanted) - not sure how to change the label to help wanted

I am trying to understand how to query an abstract base class/model via a unique model field (guaranteed unique by each end concrete model sharing the same unique_together clause(s) ). I changed the highest Parent class to the PolymorphicModel. I migrated the database using a migration written by django, then modified by me, and then migrated, and see the successful database (both django_content_types and the extra column on the concrete models).

Environment

  • Django-polymorphic version: current - 545bf7d
  • Django version: 2.1
  • Python version: 3.5 and 3.6
  • Other libraries used, if any: none to my knowledge that involve the model classes outside of native django

Code examples

// models.py

class Asset(PolymorphicModel):
    asset_id = models.CharField(max_length=100, editable=False)  # argua3y4tv9yqawnqv29…
    asset_name = models.CharField(max_length=200, editable=False)  # 10101
    account = models.ForeignKey(Account, on_delete=models.CASCADE)

    class Meta(object):
        abstract = True

class B(Asset):  # intermediate abstract class
    pass

    class Meta(object):
        abstract = True

class C(B):
    unique_feature = models.CharField(max_length=200)
    class Meta(object):
        unique_together = (('asset_id', 'account'))

class D(B):
    cake = models.CharField(max_length=200)
    class Meta(object):
        unique_together = (('asset_id', 'account'))
    

// urls.py

    url(r'^accounts/(?P<slug>[a-zA-Z]+)/assets/(?P<assetName>[a-zA-Z0-9]+)',
        AssetsViewSet.as_view({'get': 'retrieve'})),

// views.py (from a DRF viewset)

class AssetsViewSet(viewsets.ModelViewSet):
    serializer_class = AssetSerializer
    permission_classes = (permissions.IsAuthenticated, IsOrganizationMember,)


    def retrieve(self, request, slug=None, assetName=None):
        /regardless if I filter by the asset's account foregin key
        queryset = Asset.objects.filter(asset_name=assetName).select_subclasses()

This gives me the error in the browser:

AttributeError at /api/v1/accounts/FSL/assets/10101
Manager isn't available; Asset is abstract

If I remove the abstract class definition on the parent class (Asset), then the django checker during compile errors for each of the concrete classes:

app.C: (models.E016) 'unique_together' refers to field 'account' which is not local to model 'C'.
  HINT: This issue may be caused by multi-table inheritance.
app.C: (models.E016) 'unique_together' refers to field 'asset_id' which is not local to model 'C'.
  HINT: This issue may be caused by multi-table inheritance.

I am unsure how to go about keeping the database structure of what I have (Abstract tree with many intermediate abstract models and some concrete models and to be able to query against the highest [grand]Parent abstract base class.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions