理解Django中的反射以进行重构

0 投票
1 回答
507 浏览
提问于 2025-04-18 08:23

我正在做我的第一个Django项目,需要了解Django中反射的用法。

  • 我有一个叫做 category_autocomplete 的方法,我用它和jQuery一起实现类别字段的自动补全。
  • 我还需要在其他地方实现自动补全,但针对不同的内容。我觉得把它做成一个类来重复使用可能是个好主意。
  • 我已经开始制作这个类,但不知道接下来该怎么做。

问题在于Django使用 filter 函数的方式。它有一个参数,格式是 <param-name>_icontains。我可以通过使用 getattr 并将参数名作为字符串传递来轻松复现这个功能,但我不知道如何使用反射来获取 filter 函数的参数名。

有没有什么办法可以做到这一点?

class Autocomplete():
    @staticmethod
    def get_json_autocomplete(self, cur_objects, func):
        results = []
        for cur_object in cur_objects:
            results.append(func(cur_object))
        return json.dumps(results)

    @staticmethod
    def autocomplete(self, request, class_name, attr_name):
        term = request.GET.get('term', '')
        data = Autocomplete.get_json_autocomplete(
            #Problem here
            class_name.objects.filter(attr_name=term),
            lambda x: getattr(x, attr_name)
        )
        return HttpResponse(data, 'application/json')

def _get_json_autocomplete(cur_objects, func):
    results = []
    for cur_object in cur_objects:
        results.append(func(cur_object))
    return json.dumps(results)

def category_autocomplete(request):
    term = request.GET.get('term', '')
    data = _get_json_autocomplete(
        Category.objects.filter(name__icontains=term),
        lambda x: x.name
    )
    return HttpResponse(data, 'application/json')

1 个回答

1

我觉得你想要的东西是 **,你可以看看 这里这里

所以你代码的那部分可以是:

def autocomplete(self, request, class_name, attr_name):
    term = request.GET.get('term', '')
    data = Autocomplete.get_json_autocomplete(
        class_name.objects.filter(**{attr_name + '__icontains': term}),
        lambda x: getattr(x, attr_name)
    )
    return HttpResponse(data, 'application/json')

撰写回答