# Doing a Join on a django queryset

**URL:** <https://forum.djangoproject.com/t/doing-a-join-on-a-django-queryset/11072>\
**Category:** Using Django\
**Created:** [December 17, 2021, 12:13am UTC](https://forum.djangoproject.com/t/doing-a-join-on-a-django-queryset/11072 "2021-12-17T00:13:01Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![colina83](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.djangoproject.com/colina83/32/6569_2.png) [@colina83](https://forum.djangoproject.com/u/colina83)\
**Post date:** [December 17, 2021, 12:13am UTC](https://forum.djangoproject.com/t/doing-a-join-on-a-django-queryset/11072/1 "2021-12-17T00:13:01Z")

</div>

Hi All,

I want to learn the proper Django way of doing a Joint between 2 related models in Django, and I’m struggling a lot to do this, at the end I want to get just one queryset that I can render to an HTML page

```auto
class Leads(models.Model):

    project_id = models.BigAutoField(primary_key=True, serialize=False)
    created_at = models.DateTimeField(auto_now_add=True)
    expected_revenue = MoneyField(decimal_places=2,max_digits=14, default_currency='USD')
    expected_licenses = models.IntegerField()
    country = CountryField(blank_label='(select_country)')
    status = models.CharField(choices=[('Open', 'Open'), ('Closed', 'Closed'), ('Canceled', 'Canceled'),
                                       ('Idle', 'Idle')
                                       ], max_length=10)
    estimated_closing_date = models.DateField()
    services = models.CharField(choices=[('Illumination Studies', 'Illumination Studies'),
                                  ('Training', 'Training'),('Survey Design Consultancy', 'Survey Design Consultancy'),
                                  ('Software License', 'Software License'),
                                  ('Software Development','Software Development')], max_length=40)
    agent = models.ForeignKey(Profile, default='agent',on_delete=models.CASCADE)
    company = models.ForeignKey(Company,on_delete=models.CASCADE)
    point_of_contact = models.ForeignKey(Client, default='agent',on_delete=models.CASCADE)
    updated_at = models.DateTimeField(auto_now=True)
    application = models.CharField(choices=[('O&G','O&G'),('Renewables','Renewables'),('Mining','Mining'),
                                         ('Other','Other'),('CSS','CSS')],
                                default='O&G',max_length=20)
    sub_category = models.CharField(choices=[('Wind','Wind'),('Geo-Thermal','Geo-Thermal'),('Solar','Solar'),
                                             ('Tidal','Tidal')], max_length=20, blank=True)

class LeadEntry(models.Model):
    revenue = MoneyField(decimal_places=2,max_digits=14, default_currency='USD',blank=True)
    date = models.DateField()
    lead_id = models.ForeignKey(Leads,on_delete=models.CASCADE)
    id = models.BigAutoField(primary_key=True, serialize=False)
    probability = models.DecimalField(max_digits=2,
                                      decimal_places=1,
                                      default=0,
                                      validators=[MaxValueValidator(1.0,'The value should be less than 1.0'),
                                                  MinValueValidator(0.0,'The value should be more than 0.0')]
                                      )
    stage = models.CharField(choices=[('Lead','Lead'),('Deal','Deal')], default='Lead',max_length=10, blank=True)
    sales_order = models.CharField(
        max_length=9,
        validators=[RegexValidator(r'\d{4}.\d{4}', 'The value should be four digits, a character and four digits')],
        default='0000-0000',
        blank=True
    )

```

Lead ID is related to Project ID, so what I want to do is this type of Joint that I use very commonly on Pandas

merged = pd.merge(Leads ,Lead\_Entry, on=[“project\_id”])

So in the end I only want to merge the Leads that have a Lead\_entry and throw away the leads that do not have a Lead\_Entry

for example, would this be correct:

```auto
forecast = LeadEntry.objects.all()
leads = Leads.objects.all()
queryset = forecast | leads

```

Well, I just trued that and got an assertionError, so I guess that is not really the way to do it

---

<div class="post-metadata">

**Author:** ![KenWhitesell](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.djangoproject.com/kenwhitesell/32/280_2.png) [@KenWhitesell](https://forum.djangoproject.com/u/KenWhitesell)\
**Post date:** [December 17, 2021, 12:55am UTC](https://forum.djangoproject.com/t/doing-a-join-on-a-django-queryset/11072/2 "2021-12-17T00:55:47Z")

</div>

See [Making queries | Django documentation | Django](https://docs.djangoproject.com/en/4.0/topics/db/queries/#related-objects)

There’s nothing special to do.

Because of the foreign key relationship between LeadEntry and Leads, the queryset `LeadEntry.objects.all()` automatically gives you access to the related Leads.

Now, if you’re iterating over the set, you can use the `select_related` clause to avoid an N+1 query problem - `LeadEntry.objects.all().select_related('lead_id')`

If you’re looking at the query from the other direction, where you want to query on Leads that have LeadEntry objects related to it, you can use a filter: `Leads.objects.filter(leadentry__isnull=False)`, and then you can avoid the N+1 query problem in this case by using prefetch\_related.

---

<div class="post-metadata">

**Author:** ![colina83](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.djangoproject.com/colina83/32/6569_2.png) [@colina83](https://forum.djangoproject.com/u/colina83)\
**Post date:** [December 17, 2021, 3:11am UTC](https://forum.djangoproject.com/t/doing-a-join-on-a-django-queryset/11072/3 "2021-12-17T03:11:32Z")

</div>

> [@KenWhitesell](#):
>
> LeadEntry.objects.all().select\_related(‘lead\_id’)

Ken,

Thanks that is very clear, but I still get 2 distinct querysets, with exactly the same length, how can I get all the information in one queryset?, as I want to render just one queryset to the HTML so I can build a table

Regards,  
FCS

---

<div class="post-metadata">

**Author:** ![KenWhitesell](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.djangoproject.com/kenwhitesell/32/280_2.png) [@KenWhitesell](https://forum.djangoproject.com/u/KenWhitesell)\
**Post date:** [December 17, 2021, 3:16am UTC](https://forum.djangoproject.com/t/doing-a-join-on-a-django-queryset/11072/4 "2021-12-17T03:16:41Z")

</div>

I don’t understand. What do you mean you’re getting two distinct querysets? Please post your view.

This statement:

> [@KenWhitesell](#):
>
> LeadEntry.objects.all().select\_related(‘lead\_id’)

is only going to give you one queryset.

---

<div class="post-metadata">

**Author:** ![colina83](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.djangoproject.com/colina83/32/6569_2.png) [@colina83](https://forum.djangoproject.com/u/colina83)\
**Post date:** [December 17, 2021, 2:17pm UTC](https://forum.djangoproject.com/t/doing-a-join-on-a-django-queryset/11072/5 "2021-12-17T14:17:10Z")

</div>

Ken,

Please see below my view using select\_related, returning only one queryset

```auto
@login_required
def forecast_table(request):
    forecast = LeadEntry.objects.all().select_related('lead_id')

    return render(request,'account/forecast_table.html',{'forecast':forecast
                                                         })

```

The result is a queryset that contains all my Lead\_Entry with the correspondent information in the LeadEntry table, but how can I access the related information from the Lead table ?

example

```auto
  for i in forecast:
        print(i.stage)  

```

gives me stage variable in LeadEntry

If I do the following:

```auto
  for i in forecast:
        print(i.country)  

```

I get an error, AttributeError: ‘LeadEntry’ object has no attribute ‘country’

My question is how do I go about and getting that information from the Leads table, which is related to the same project\_id /lead\_id

---

<div class="post-metadata">

**Author:** ![colina83](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.djangoproject.com/colina83/32/6569_2.png) [@colina83](https://forum.djangoproject.com/u/colina83)\
**Post date:** [December 17, 2021, 2:38pm UTC](https://forum.djangoproject.com/t/doing-a-join-on-a-django-queryset/11072/6 "2021-12-17T14:38:00Z")

</div>

Ken,

I got how it works, you have to use the related key name in order to get access to the data in the other model

```auto
    for i in forecast:
        print(i.lead_id.country)

```

Everything makes sense now
