Hi I have two models with m2m link through third model:
class Group(UsefulAbstractModel):
hotels = models.ManyToManyField(
Hotel,
through='HotelDetails',
related_name='groups', )
class Hotel(UsefulAbstractModel):
name = models.CharField(
max_length=255,)
class HotelDetails(models.Model):
hotel = models.ForeignKey(
Hotel,
related_name='hotel_details', )
group = models.ForeignKey(
Group,
related_name='hotel_details', )
num = models.IntegerField(
validators=[
MaxValueValidator(2),
MinValueValidator(1), ], )
All groups has two hotel links with numbers 1 and 2. I need to display it in admin group interface. I create two custom columns for each hotel:
class GroupAdmin(admin.ModelAdmin):
def first_hotel(self, instance):
return instance.hotel_details.filter(num=1).first().hotel
def second_hotel(self, instance):
return instance.hotel_details.filter(num=1).first().hotel
But for every instance I have 2 additional query now.
I tried to override queryset method, but in not helped:
def queryset(self, request):
return super(GroupAdmin,self).queryset(request).prefetch_related('hotels')
The problem is that you are filtering the prefetched results with filter(num=1). This causes Django to do a new query.
You can use a Prefetch object to fetch the correct queryset. Note you should override the model admin's get_queryset method, not queryset.
def get_queryset(self, request):
return super(GroupAdmin,self).get_queryset(request).prefetch_related(
Prefetch('hotel_details', queryset=HotelDetails.objects.filter(num=1).select_related('hotel'), to_attr='hotel_details_num1'),
)
Then change your model admin methods to use the new queryset, for example:
def first_hotel(self, instance):
return instance.hotel_details_num1.first().hotel
See the docs for more into about prefetch_related and Prefetch objects.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With