3

I am using django-model-utils for inheritance Managers. I want to get results of only one subclass at a time.

managers.py

from model_utils.managers import InheritanceManager
class PostManager(InheritanceManager):
    pass

models.py

from .managers import PostManager
class Post(models.Model):
    title = models.CharField(max_length=20)
    text = models.TextField()
    objects = PostManager()


class ImagePost(Post, models.Model):
    source = models.URLField()
    image = models.ImageField(upload_to="images/%Y/%m/%d")


class VideoPost(Post, models.Model):
    source = models.URLField()

I want to return results of only image type. by writing a simpler query like this.

Post.objects.filter(type='image').select_subclasses()

What i have tried:

if type == 'image':
    Post.objects.filter(imagepost__isnull=False).select_subclasses()

This works but is kind of anti-pattern, i don't want to write conditions in views for every content type.

Is there better way like defining a property in models or converting it into a manager method? or am i missing something?

Shang Wang
  • 24,909
  • 20
  • 73
  • 94
Siddhesh Suthar
  • 425
  • 7
  • 9
  • No such field 'type' in 'Post' model. Did you miss this field in 'Post' model? – Anoop May 09 '16 at 13:21
  • `Post.objects.filter(imagepost__isnull=False).select_subclasses()` How does this work? Do you have a `ForeignKey` to `Post` in `ImagePost`? What is the purpose of `select_subclasses()`? – AKS May 09 '16 at 13:48
  • @Anoop : i want to do it this way, adding a static field 'type' won't give desired results too. In what way i can add that field in order to make it query-able. – Siddhesh Suthar May 09 '16 at 14:10
  • @AKS: edited the question. I am using the Inheritance manager from django-model-utils https://django-model-utils.readthedocs.io/en/latest/managers.html#inheritancemanager – Siddhesh Suthar May 09 '16 at 14:13

1 Answers1

2

Have you tried to pass the class to select_subclasses method?

Post.objects.select_subclasses(ImagePost)

Check their doc about this feature.

Edit:

I misunderstood the question, but sounds like OP wants only the Post with type ImagePost. Doing select_subclasses(ImagePost) would fetch everything and convert the objects with type ImagePost to ImagePost instances. The solution should be as simple as :

image_posts = ImagePost.objects.all()
Shang Wang
  • 24,909
  • 20
  • 73
  • 94
  • I was also just reading that. It seems that this will still result in all the objects just that the image posts will be the instances of `ImagePost` and rest of them will be the instances of `Post` class. Checkout this comment ... `restaurants will be Restaurant instances, bars will still be Place instance` – AKS May 09 '16 at 14:47
  • Hmm, I misunderstood your requirement. How about just doing `ImagePost.objects.filter(...)`? I know that it's repetitive to write multiple `if` statements but you might be able to get away with it by referring different models depend on what type do you have. – Shang Wang May 09 '16 at 14:52
  • 1
    yup thats the way to do it. only doing select_subclasses(ImagePost) doesn't omit other results, so had to do this imagepost__isnull=False. ImagePost.objects.filter() is much cleaner. for removing if else, I defined it in url : {'content_class':ImagePost} and accessed it in view. self.model = self.kwars.get('content_class') self.model.objects.filter(...) Thanks for your answer :) – Siddhesh Suthar May 09 '16 at 15:55