0

I have a model for a company. Then I have a base model for company posts. It contains common posts attributes. An attribute is the company that publishes the posts. It refers to the Company model with a ForeignKey. Finally I have a child model (based on the CompanyPost base model) for posts of type A:

class Company(models.Model):
    name = models.CharField(...)
    ...


class CompanyPost(models.Model):
    company = models.ForeignKey(Company,...)
    ...


class PostA(CompanyPost):
    name = ...

In a template I want to loop over posts of type A published by a specific company.
I tried these variants:

1)

{% for postA in company.companyposts_set.all.postA_set.all %}
...

2)

{% for companyposts in company.companypost_set.all %}
{% for postA in companyposts.postA_set.all %}
...
{% endfor %}{% endfor %}

I tried other sub-variants of the above. None seems to work.
I know that I can easily prepare the set in the view, like:

postsA = PostA.objects.filter(company__pk=pk)

And pass postsA to the template context, but I'm wondering whether there is a way to loop over related models' children in the template.
(note: looping over companyposts works. But I get of course all types of posts, like postB etc.:

{% for post in company.companypost_set.all %}

That is why I tried variant 2) above to loop again over the results.)
Thank you in advance.

UPDATE: Thank you all for your answers. I understand that, by choosing model inheritance, I chose a convoluted solution. In the present post I'm asking whether displaying related model's children in a template is possible. In order not to confuse questions, in this question I explain why I used concrete model inheritance and ask what would be a better solution.

Oxfos
  • 71
  • 1
  • 7
  • Do you really need model inheritance for your posts ? – bruno desthuilliers Dec 18 '19 at 09:44
  • this being said, something like `company.posta_set.all()` should work (not tested, I don't have any model with concrete inheritance in my projects). – bruno desthuilliers Dec 18 '19 at 09:45
  • I'm using model inheritance because I read that it would give more flexibility down the road and because otherwise it would be difficult to loop over a set/list containing instances from different models with different attributes/methods. Looping over the parent model instances would be easier. However I've had more difficulty with looping over parent instances because the parent instance cannot 'know' which child class (PostA or PostB) the child instance belongs to. `company.posta_set.all` does not work (`company.companypost_set.all` does work, as I wrote). – Oxfos Dec 18 '19 at 20:17
  • My question wasn't clear, sorry. I meant : are there any differences between PostA and PostB, and if yes is there a need for _concrete_ inheritance? – bruno desthuilliers Dec 18 '19 at 20:20
  • @brunodesthuilliers yes there are differences. But the actual reason for the choice was that I could more easily loop through all posts via the parent than by merging different model's instances. In the update I put a link to the question whether the choice of concrete inheritance is the best one, as it is a different question. – Oxfos Dec 18 '19 at 21:52

1 Answers1

0

If you don't want to define it in the views, you could define it as a property of Company objects.

@property
def post_a_set(self):
    return PostA.objects.filter(company__pk=self.pk)

I'm pretty sure it's the model inheritance that is causing the problems, and dimly remember seeing something like his documented. I'd echo, do you really need concrete model inheritance here? Other approaches are wider CompanyPost objects with a post_type choices field and other fields null or blank if inappropriate; or a post_type field and the data that applies only to that type stored as a JSON string or (if you are using Postgresql) a JSONField.

nigel222
  • 7,582
  • 1
  • 14
  • 22