Django中如何按@property定义的关联数量对多对多关系排序?
Django后台多对多字段按关联数量排序解决方案
嗨,我来帮你搞定这个Django后台的排序问题!先理清楚你的场景:你有Site和Product的多对多关系,Product里定义了sites_count属性统计关联站点数量,现在想在SiteAdmin的多对多选择框里,让Product按这个数量排序对吧?
你的现有代码
先把你给出的模型和Admin类片段整理出来:
模型代码
from django.db import models class Site(models.Model): articles = models.ManyToManyField(Article, blank=True, null=True) products = models.ManyToManyField(Product, blank=True, null=True) class Product(models.Model): @property def sites_count(self): return self.site_set.count()
现有Admin类片段
class SiteAdmin(admin.ModelAdmin): def formfield_for_manytomany(self, db_field, request, **kwargs): if db_field.name == "articles": # 你原来的代码片段 ...
实现排序的关键修改
这里要注意:模型里的sites_count是Python层面的属性,没法直接用于数据库级别的排序。我们需要用Django ORM的annotate方法,在数据库层面计算每个Product关联的Site数量,再基于这个结果排序。
完整的SiteAdmin代码如下:
from django.contrib import admin from django.db.models import Count from .models import Site, Article, Product class SiteAdmin(admin.ModelAdmin): def formfield_for_manytomany(self, db_field, request, **kwargs): # 处理products多对多字段的排序逻辑 if db_field.name == "products": # 注释出每个Product关联的站点数量,按数量倒序排序 kwargs["queryset"] = Product.objects.annotate( sites_count=Count('site') ).order_by('-sites_count') # 如果articles字段也需要类似排序,可以在这里添加对应逻辑 elif db_field.name == "articles": # 比如若Article也有统计需求,同样用annotate+order_by实现 pass # 调用父类方法返回处理后的字段 return super().formfield_for_manytomany(db_field, request, **kwargs)
补充说明
Count('site')用于统计每个Product关联的Site数量,这里的site是反向关联的默认名称(对应Site模型的小写形式)。order_by('-sites_count')表示按站点数量倒序排列,若要正序排序,去掉负号改成'sites_count'即可。- 这个修改会覆盖
products多对多字段的默认查询集,让后台选择框里的产品按关联站点数量排序展示。
内容的提问来源于stack exchange,提问作者Tinker
相关产品推荐
相关产品推荐

