0

I have two models, field of one of them pointing to the other as shown below:

class Group(models.Model):
    group_company_id = models.CharField(primary_key=True, ...)
    
class Company(models.Model):
    company_id = models.CharField(primary_key=True, ...)
    group_company = models.ForeignKey(Group, related_name="related_grp_company", ...)

I am trying to get all the Companies that have been created for a particular Group. So I am trying to get the company_id (and other) values in Djnago UpdateView as a list in the template. My CBV is as shown:

class GroupCompanyChangeView(UpdateView):
    template_name =  ...
    model = Group
    form_class = ...
    success_url = reverse_lazy('group_list')

    grp_coy_units = Group.objects.prefetch_related('related_grp_company') # I am trying to get the values of `company_id` in the template but nothing is displayed.

Could somebody please let me know how to get this to work?

Update

As explained (@Mahmoud Adel), I have modified my UpdateView as shown below:

class GroupCompanyChangeView(UpdateView):
    template_name =  ...
    model = Group
    form_class = ...
    success_url = reverse_lazy('group_list')

    def get_object(self, *args, **kwargs):
        return Group.objects.get(pk=self.kwargs['pk'])

And then in the template, I am doing:

{{ group.related_grp_company }}

With this I am getting an output of <app>.Company.None.

shaan
  • 351
  • 2
  • 15

1 Answers1

1

UPDATE: After testing on my local env to solve the problems reported in the comments, this is the final answer

You should override get_object()

def get_object(self, *args, **kwargs):
        try:
            return Group.objects.prefetch_related('related_grp_company').get(pk=self.kwargs['pk'])
        except:
            return None

Note that order matter here in the above query, doing prefetch_related before get fixes the error for 'Group' object has no attribute 'prefetch_related'.

Also, you can drop using prefetch_related and only do get from the above query and it will work too, but using prefetch_related is suggested to optimize performance as you will fetch the related companies every time

Then at your template you can simply call related_grp_company.all from the object, let's say that you are passing the current Group object as group to your template, so it should like group.related_grp_company.all, this is a QuerySet list, so loop over it or do whatever you want.

for ex:

{%for d in object.related_grp_company.all%}
<h1>{{ d.company_id }}</h1>
{% endfor %}

Because we didn't add all we were getting<app>.Company.None earlier

Tip:

related_name is used for the reverse relation, I would suggest renaming it to companies so it would be more clearer, for ex:

group_company = models.ForeignKey(Group, related_name="companies", ...)

so using it later will be like group.companies()

Mahmoud Adel
  • 1,262
  • 2
  • 13
  • 23
  • Thanks for your answer. I am getting error `Company matching query does not exist.` Am I missing something? I have put the override in the ** GroupCompanyChangeView** `UpdateView`. – shaan Nov 29 '20 at 09:40
  • this may be raised because a company with the requested id doesn't exist, did you try using `get_object_or_404()` as shown in the answer? – Mahmoud Adel Nov 29 '20 at 10:34
  • Actually as I have already put in my question, I am trying to get all **companies** in the **Group**. And yes, there are **companies** under the **Group**. Anyway, using `get_object_or_404()` I am getting error `'Company' object has no attribute 'prefetch_related'`. – shaan Nov 29 '20 at 10:45
  • ah sorry my fault, The answer was for getting all group objects related to company I have updated the answer for `Group` – Mahmoud Adel Nov 29 '20 at 11:14
  • I may not have understood it correctly, but I am getting `.Company.None` in the template. Just to demonstrate it the way I have done it (and that I understood your explanation correctly), I am updating my question above. Please check. – shaan Nov 29 '20 at 11:42
  • The reason for `None` at `template` is that, the related data is not loaded by django as it ORM is `lazy loading` by default and a template won't make a new query to get anything, I have updated the answer with `prefetch_related` to fix that – Mahmoud Adel Nov 29 '20 at 12:20
  • Nope. The same problem persists `'Group' object has no attribute 'prefetch_related'`!! – shaan Nov 29 '20 at 12:51
  • I know why this is happening now, see https://stackoverflow.com/a/39818183/4984493 – Mahmoud Adel Nov 29 '20 at 13:01
  • can you try using `select_related` instead of `prefetch_related`? – Mahmoud Adel Nov 29 '20 at 13:06
  • Same problem **`'Group' object has no attribute 'select_related'`**!! – shaan Nov 29 '20 at 13:14
  • I will try it at my local env and get back to you – Mahmoud Adel Nov 29 '20 at 15:05
  • I have tested on my local env and updated my answer with the final answer, everything should work fine now – Mahmoud Adel Nov 30 '20 at 08:43
  • As you have noticed my comment at [this discussion](https://stackoverflow.com/a/30348720), in fact the issue was resolved yesterday itself with the help of this instant answer. However, it was thanks to you that helped me majorly in my query. **Another matter. In the `get_object` override, I could do without the`try` / `except` bits**. Doesn't throw any problem. Marking your answer. Thanks a bunch!! – shaan Nov 30 '20 at 13:36
  • 1
    I'm happy that things are working smoothly with you now! thank you too and have a nice day :) – Mahmoud Adel Nov 30 '20 at 15:27