0

So, the issue is pretty simple but I couldn't find any info related to it

>>> Match.objects.all()[0].team_set.all()
<QuerySet [<Team: EG>, <Team: Liquid>]>
>>> Match.objects.all()[0].team_set.all()[1:2]
<QuerySet [<Team: Liquid>]>
>>> Match.objects.all()[0].team_set.all()[0:1]
<QuerySet [<Team: Liquid>]>
>>> Match.objects.all()[0].team_set.all()[0]
<Team: Liquid>
>>> Match.objects.all()[0].team_set.all()[1]
<Team: Liquid>

Basically it refuses to give me ForeignKey object by its index. Any ideas?

5
  • This is not that strange at all. The database can return data in any possible order. It is also inefficient to access by index. One normally iterates over a queryset. This will fetch all objects in memory in a single query. Commented Mar 10, 2020 at 18:38
  • If you would use team_set.order_by('pk')[0] for example, then you set the order, and thus then this shoud not happen. Commented Mar 10, 2020 at 18:39
  • It is for example possible that the Match object Match.objects.all()[0] is different as well. Commented Mar 10, 2020 at 18:40
  • @WillemVanOnsem I found it weird because this type of referencing worked with sqlite3. But, for example, when editing html template, I need to reference both first and second Team obj related to Match to therefore insert their fields' values into the template. Is there any way I could turn the queryset into an iterator, for example using {% with ... %}? Commented Mar 10, 2020 at 18:43
  • So you "found it weird because ... worked with sqlite3".That's like finding it weird that my C++ code doesn't work in Java. Sqlite3 and Oracle are different products. Don't expect them to work the same it just doesn't happen. Commented Mar 10, 2020 at 18:53

1 Answer 1

1

Basically it refuses to give me ForeignKey object by its index. Any ideas?

Unless you specify an order, a database can return the records in any possible order. Hence that means that making the same (unordered) query multiple times, can each time yield a different result.

It is therefore advisable to use .order_by() [Django-doc] if something should have a deterministic order. For example in case of pagination, not doing so, can break the pagintion.

Here you thus can inspect the query with:

Match.objects.order_by('pk')[0].team_set.order_by('pk')
Match.objects.order_by('pk')[0].team_set.order_by('pk')[0]
Match.objects.order_by('pk')[0].team_set.order_by('pk')[0:1]
Match.objects.order_by('pk')[0].team_set.order_by('pk')[1]
Match.objects.order_by('pk')[0].team_set.order_by('pk')[1:2]

That being said, accessing objects by id, is not very efficient: this will make *a query to the database per index. It is therefore better to aim to "batch" the queries, and thus make one query, that fetches for example two records.

For example you can obtain the first two records and perform iterable unpacking:

team1, team2 = Match.objects.order_by('pk')[0].team_set.order_by('pk')[:2]

Here team1 is the first team, and team2 is the second. This will raise an error if there are no two teams (but since it is a Match this is likely not the case). You can then pass the two teams for example to the template.

Sign up to request clarification or add additional context in comments.

1 Comment

Thanks, I will notice that in the future. As for the response to the question I posted in the comments section above, I used dictsort filter to be able to use indexing in the template file.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.