Django w/django_filters 按方法或非模型字段查找

Django w/django_filters lookups by methods or non-model fields

版本:Django 3.0.6、Python3.8、MySQL8.0、django_filters2.3.0

请耐心等待,因为我不确定我是否正确地为问题命名。我先从相关代码说起:

models.py

class Vendor(models.Model):
    name = models.CharField(max_length=50)
    
class Category(models.Model):
    name = models.CharField(max_length=50)
    
class Product(models.Model):
    name = models.CharField(max_length=50)
    vendor = models.ForeignKey('Vendor', on_delete=models.SET_NULL, null=True)
    category = models.ForeignKey('Category', on_delete=models.SET_NULL, null=True)
    
class Rating (models.Model):
    score = models.PositiveIntegerField(default=0, validators=[MaxValueValidator(10)])
    product = models.ForeignKey('Vendor', on_delete=models.SET_NULL, null=True)
    
    def category(self):
        return self.product.category
        
    def vendor(self):
        return self.product.vendor

filters.py

from .models import Vendor, Category, Product, Rating
import django_filters

class RatingFilter(django_filters.FilterSet):
    rating_filter = django_filters.RAngeFilter(field_name='score', lookup_expr='range')
    
    class Meta:
        model = Rating
        fields = '__all__'

views.py

from .filters import RatingFilter

def RatingSearch(request):
    rating_list=Rating.objects.all()
    rating_filter = RatingFilter(request.GET, queryset=rating_list)
    return render (request, 'inventory/rating_search.html', { 'filter': rating_filter})

从基本的 SQL 角度来看,我知道我可以使用模型作为大纲,并通过建立表之间的关系来按类别或供应商过滤对评级记录的搜索。我的目标是使用 django_filters 在网络表单上做同样的事情。

开箱即用,按产品 and/or 分数过滤评级非常容易。我似乎无法弄清楚的是我如何根据一条没有直接从模型中引用的信息进行过滤。当我查看评级的详细信息时,我无需执行任何特殊操作即可让类别方法 {{ rating.category }} 完成工作。然而,过滤器 class 似乎更抽象一些,文档让我大部分时间都摸不着头脑。

我可以将类别和供应商字段复制到评级对象,但这感觉就像到处都是黑客。我花了几个小时试图找到其他人做类似的事情,但我觉得我没有使用正确的术语进行搜索,或者我只是遗漏了一些非常明显的东西。

来自documentation

field_name: The name of the model field to filter on. You can traverse “relationship paths” using Django’s __ syntax to filter fields on a related model. ex, manufacturer__name.

看来您基本上可以执行以下操作:

rating_filter = django_filters.RangeFilter(
    field_name='product__category', lookup_expr='range')