12833

Django model inheritance, filtering models

Given the following models:(don't mind the TextFields there're just for illustration)

class Base(models.Model): field1 = models.TextField() class Meta: abstract=True class Child1(Base): child1_field = models.TextField() class Child2(Base): child2_field = models.TextField() class Content(models.Model): aso_items = models.ManyToManyField('Base')

According to these definitions a Content object can be associated with more than one Base object, eg. an interview(=Content object) can be linked with a musician(=Child1 object), a filmdirector(=Child2), etc.

Now, for my question: Is it possible to filter Content objects according to which model the aso_items field points to? An example : Say I would like a Queryset containing all the Content objects that are associated with a specific object of Child1(eg. all the interviews associated with the musician Bob Dylan), how can I achieve this?

Further, what if I'd want a QuerySet containing all the Content objects that are associated with Child1 objects?(eg. all the interviews that associated with musicians) How does this change the filtering?

Thanks in advance ps: I'm experiencing some problems with white space in the preview, forgive me

Answer1:

You should check the section of the Django docs regarding using related_name for abstract base classes. http://docs.djangoproject.com/en/dev/topics/db/models/#be-careful-with-related-name

To quote the docs:

If you are using the related_name attribute on a ForeignKey or ManyToManyField, you must always specify a unique reverse name for the field. This would normally cause a problem in abstract base classes, since the fields on this class are included into each of the child classes, with exactly the same values for the attributes (including related_name) each time.

To work around this problem, when you are using related_name in an abstract base class (only), part of the name should be the string %(class)s. This is replaced by the lower-cased name of the child class that the field is used in. Since each class has a different name, each related name will end up being different.

Using this information I would recommend moving the m2m field into the Base class:

class Content(models.Model): # Add remaining fields for Content pass class Base(models.Model): field1 = models.TextField() items = models.ManyToManyField(Content,related_name="%(class)s_related") class Meta: abstract=True class Child1(Base): child1_field = models.TextField() class Child2(Base): child2_field = models.TextField()

Answer2:

Apparently a ForeignKey relation(or ManyToMany for that matter) with a abstract class isn't allowed. I get the following error : 'AssertionError: ForeignKey cannot define a relation with abstract class Artiest'.

A possible solution is to define the base class as non-abstract, however this implies that one could instantiate models of the base class. Which isn't the behavior I want.(after all it was an abstract class) Has someone come accross the same problem how did you solve it? Any alternatives?

Answer3:

Have a look at http://www.djangoproject.com/documentation/models/generic_relations/ which goes through generic relations. Your Content model would match up to their TaggedItem model, and your Base model would match up to their Animal/Vegetable/Mineral model (with Child1 and Child2 extending).

Getting all of the Content objects for a single child would be (assuming you set the GenericRelation to contents inside Base):

child_contents = childObject.contents.all()

And to get all Content objects for a model:

ctype = ContentType.objects.get_for_model(Child1) all_child_contents = Content.objects.filter(content_type=ctype)

Recommend

  • show xml in tree format with the help of jqGrid/treegrid
  • Queue TFS 2012 build from Jenkins
  • Value assigned is not used in any execution path - C# [duplicate]
  • How to alter the display of what Spacebars outputs?
  • [] is not identical to [] [duplicate]
  • How do I set breakpoints using the Photran IDE in Eclipse?
  • ViewExpiredException in Firefox and IE after migrating to Jboss 7.0 AS [duplicate]
  • How to capture worksheet being added through Copy/Paste in Excel VBA
  • Entity Framework v4 and underscores in column names
  • Meteor stuck at Extracting meteor-tool@1.4.0-1
  • How to use Xcode Extract refactoring feature?
  • Create child Window of another process's HWND? (e.g. screensaver preview)
  • LyX — Title, Abstract, Keywords Missing When Using Elsevier Class in View
  • Why do GeoJSON features appear like a negative photo of the features themselves?
  • Get variable height for a UIButton for iPhones 5/6/6+
  • Mongodb update() vs. findAndModify() performace
  • Problem in concatenation of objects in javascript
  • Jquery UI Sortable, move item automatically
  • PHP + XML - how to rename and delete XML elements using SimpleXML or DOMDocument?
  • Get current user from inside the model in Sails
  • Find longest path less than or equal to given value of an acyclic, directed graph in Python
  • Java : How to tint this PNG programmatically?
  • Embedded Google Maps in Rails not responsive
  • EntLib Way to Bind “Null” Value to Parameter
  • Cross platform UI spacing/padding
  • How to split circle in to the sectors in google maps?
  • How can I set a binding to a Combox in a UserControl?
  • Does it make sense to call System.gc() and Thread.sleep() when working on Bitmaps?
  • How to avoid particles glitching together in an elastic particle collision simulator?
  • Android fill_parent issue
  • Recording logins for password protected directories
  • Splitting given String into two variables - php
  • Problems to linebreak with an int in JLabel
  • How to draw moving and Running sine wave chart using JFree chart in java?
  • Is possible to count alias result on mysql
  • TFS: Get latest causes slow project reloading
  • Check if a string to interpolate provides expected placeholders
  • 0x202A in filename: Why?
  • Benchmarking RAM performance - UWP and C#
  • How does Linux kernel interrupt the application?