简体   繁体   English

如何使用prefetch_related在admin list_display中获取自定义列的相关模型?

[英]How I can get related model for custom column in admin list_display with prefetch_related?

Hi I have two models with m2m link through third model: 嗨,我有两个模型通过第三个模型进行m2m链接:

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. 所有组都有两个带有数字1和2的酒店链接。我需要在管理组界面中显示它。 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. 但是对于每个实例,我现在有2个附加查询。
I tried to override queryset method, but in not helped: 我试图覆盖queryset方法,但没有帮助:

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) . 问题是您正在使用filter(num=1)过滤预取的结果。 This causes Django to do a new query. 这导致Django进行新查询。

You can use a Prefetch object to fetch the correct queryset. 您可以使用Prefetch对象来获取正确的查询集。 Note you should override the model admin's get_queryset method, not queryset . 注意,您应该覆盖模型管理员的get_queryset方法,而不是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. 有关更多关于prefetch_relatedPrefetch对象的信息,请参阅文档

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM