Why the first() method and slices works differently in Django?
Question:
I have the model:
class PhotoAlbum(models.Model):
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False, auto_created=True)
name = models.CharField(max_length=50, verbose_name='Album name')
type = models.ForeignKey(AlbumType, on_delete=models.CASCADE, verbose_name='Album type')
created_at = models.DateTimeField(auto_now_add=True)
And i have this code:
print(PhotoAlbum.objects.all().first())
print(PhotoAlbum.objects.all()[:1].get())
it seemed to me that the same objects should be displayed, but different ones are returned.
What’s going on, isn’t it an identical design?
Answers:
If the queryset is not ordered then first()
orders the queryset by the primary key so:
from django.db import connection
Pet.objects.all().first()
print(connection.queries[-1]['sql'])
# SELECT ... FROM <table> ORDER BY <table>."id" ASC LIMIT 1
But slicing the queryset performs no such default ordering.
from django.db import connection
Pet.objects.all()[:1].get()
print(connection.queries[-1]['sql'])
# SELECT ... FROM <table> ASC LIMIT 1
I have the model:
class PhotoAlbum(models.Model):
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False, auto_created=True)
name = models.CharField(max_length=50, verbose_name='Album name')
type = models.ForeignKey(AlbumType, on_delete=models.CASCADE, verbose_name='Album type')
created_at = models.DateTimeField(auto_now_add=True)
And i have this code:
print(PhotoAlbum.objects.all().first())
print(PhotoAlbum.objects.all()[:1].get())
it seemed to me that the same objects should be displayed, but different ones are returned.
What’s going on, isn’t it an identical design?
If the queryset is not ordered then first()
orders the queryset by the primary key so:
from django.db import connection
Pet.objects.all().first()
print(connection.queries[-1]['sql'])
# SELECT ... FROM <table> ORDER BY <table>."id" ASC LIMIT 1
But slicing the queryset performs no such default ordering.
from django.db import connection
Pet.objects.all()[:1].get()
print(connection.queries[-1]['sql'])
# SELECT ... FROM <table> ASC LIMIT 1