Django:使用Django-tables2和Django-filter搜索结果



我想通过搜索表单检索模型的对象,但添加另一列作为搜索分数。我不确定如何使用django-tables2和django过滤器来实现这一点。

将来,我希望用户能够使用django过滤器来帮助过滤搜索结果。我可以从PeopleSearchListView访问表单变量,但也许集成django表单进行表单处理是更好的方法?

到目前为止,我的想法是在get_queryset()中处理get请求,然后在将查询集发送到PeopleTable之前修改查询集,但向查询集添加另一列似乎不是标准方法。

tables.py

class PeopleTable(tables.Table):
score = tables.Column()
class Meta:
model = People
template_name = 'app/bootstrap4.html'
exclude = ('id',)
sequence = ('score', '...')

views.py

class PeopleFilter(django_filters.FilterSet):
class Meta:
model = People
exclude = ('id',)
class PeopleSearchListView(SingleTableMixin, FilterView):
table_class = PeopleTable
model = People
template_name = 'app/people.html'
filterset_class = PeopleFilter

def get_queryset(self):
p = self.request.GET.get('check_this')
qs = People.objects.all()
####
# Run code to score users against "check_this".
# The scoring code I'm using is complex, so below is a simpler
# example.
# Modify queryset using output of scoring code?
####
for person in qs:
if person.first_name == 'Phil' and q == 'Hey!':
score = 1
else:
score = 0
return qs

urls.py

urlpatterns = [
...
path('search/', PeopleSearchListView.as_view(), name='search_test'),
... ]

models.py

class People(models.model):
first_name = models.CharField(max_length=200)
last_name = models.CharField(max_length=200)

编辑:评分算法比上面的例子稍微复杂一些。它需要对People表中的所有行进行全面检查,以生成分数矩阵,然后将每个得分行与搜索查询进行最终比较。这不是一次性的分数。例如:

def get_queryset(self):
all = []
for person in qs:
all.append(person.name)
# Do something complex with all,
# e.g., measure cosine distance between every person,
# and finally compare to the get request
scores = measure_cosine(all, self.request.GET.get('check_this'))
# We now have the scores for each person.





因此,您可以在初始化表时添加额外的列。

我有几个表,它们根据系统中的事件来执行此操作;

def __init__(self, *args, **kwargs):
"""
Override the init method in order to add dynamic columns as
we need to declare one column per existent event on the system.
"""
extra_columns = []
events = Event.objects.filter(
enabled=True,
).values(
'pk', 'title', 'city'
)
for event in events:
extra_columns.append((
event['city'],
MyColumn(event_pk=event['pk'])
))
if extra_columns:
kwargs.update({
'extra_columns': extra_columns
})
super().__init__(*args, **kwargs)

因此,当提供了分数时,您可以添加类似的分数列。也许可以将你的分数从视图传递到表中,这样你就可以识别出它们的存在并添加列,然后在呈现列时使用数据。

extra_columns似乎不在tables2文档中,但您可以在此处找到代码;https://github.com/jieter/django-tables2/blob/master/django_tables2/tables.py#L251

当您为django-tables2定义一个不包含在表数据或查询集中的新列时,您应该提供一个渲染方法来计算它的值。

如果需要复杂的筛选、预处理或联接,则不必覆盖get_queryset。

在你的餐桌课上:

class PeopleTable(tables.Table):    
score = tables.Column(accessor="first_name")
class Meta:
model = People
def render_score(self, record):
return 1 if record["first_name"] == "Phil" and q == "Hey!" else 0

在您的视图中,您可以使用get_context_data:覆盖并提供复杂的数据以及特殊的过滤或聚合

def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context["filter"] = self.filter
aggs = {
"score": Function("..."),
"other": Sum("..."),
}
_data = (
People.objects.filter(**params)
.values(*values)
.annotate(**aggs)
.order_by(*values)
.distinct()
)
df = pandas.DataFrame(_data)
df = df....
chart_data = df.to_json()
data = df.to_dict()...

self.table = PeopleTable(data)
context["table"] = self.table      
context['chart_data']=chart_data
return context

最新更新