2

我正在尝试构建一个搜索页面,该页面将允许用户找到满足特定阈值标准的模型的任何实例,并且在避免严重冗余代码时遇到了麻烦。我希望有更好的方法来做到这一点。这是一个稍微做作的示例,应该说明我正在尝试做的事情,并在最后调整了相关代码。用户将使用复选框与搜索进行交互。

模型.py:

class Icecream(models.Model()):
    name = models.CharField()
    bad_threshold = models.IntegerField()
    okay_threshold = models.IntegerField()
    tasty_threshold = models.IntegerField()
    delicious_threshold = models.IntegerField()

视图.py:

def search_icecreams(request):
    user = request.user
    q_search = None

    if 'taste_search' in request.GET: 
        q_search = taste_threshold_set(request, user, q_search)

    if q_search == None:
        icecream_list = Icecream.objects.order_by('name')
    else:
        icecream_list = College.objects.filter(q_search)

    context = { 'icecream_list' : icecream_list }
    return render(request, '/icecream/icecreamsearch.html', context)

我想减少的相关代码如下,这几乎直接来自我的项目,名称已更改。

def taste_threshold_set(request, user, q_search):
    threshold = request.GET.getlist('taste_search')
    user_type_tolerance = user.profile.get_tolerance_of(icea

    # 1-5 are the various thresholds. They are abbreviated to cut down on the
    # length of the url.
    if '1' in threshold:
        new_q = Q(bad_threshold__gt = user.profile.taste_tolerance)        

        if q_search == None:
            q_search = new_q
        else:
            q_search = (q_search) | (new_q)

    if '2' in threshold:
        new_q = Q(bad_threshold__lte=user.profile.taste_tolerance) & \
            ~Q(okay_threshold__lte=user.profile.taste_tolerance)

        if q_search == None:
            q_search = new_q
        else:
            q_search = (q_search) | (new_q)

    if '3' in threshold:
        new_q = Q(okay_threshold_3__lte=user.profile.taste_tolerance) & \
            ~Q(tasty_threshold__lte=user.profile.taste_tolerance)

        if q_search == None:
            q_search = new_q
        else:
            q_search = (q_search) | (new_q)

    if '4' in threshold:
        new_q = Q(tasty_threshold__lte=user.profile.taste_tolerance) & \
            ~Q(delicious_threshold__lte=user.profile.taste_tolerance)

        if q_search == None:
            q_search = new_q
        else:
            q_search = (q_search) | (new_q)

    if '5' in threshold:
        new_q = Q(delicious_threshold__lte = user.profile.taste_tolerance)        

        if q_search == None:
            q_search = new_q
        else:
            q_search = (q_search) | (new_q)

    return q_search

基本上我希望用户能够找到满足给定阈值级别的某个对象的所有实例。例如,所有他们认为不好的冰淇淋和所有他们认为好吃的冰淇淋。

这段代码有很多我不满意的地方。我不喜欢检查 Q 对象是否尚未针对每个可能的阈值实例化,但看不到绕过它的方法。此外,如果这是一个非 django 问题,我会使用一个循环来检查每个给定的阈值,而不是把每个阈值都写出来。但同样,我不知道该怎么做。

最后,最大的问题是,我需要检查模型可能有 20 个不同属性的阈值。就目前而言,我必须为每个都编写一个新的阈值检查器,每个都与另一个略有不同(他们正在检查的属性的名称)。我希望能够编写一个通用检查器,然后将其传递给特定属性。有没有办法解决这个问题,或者我的其他两个问题?

谢谢!

4

2 回答 2

1

您应该使用 ownQuerySet作为模型def taste_threshold_set(...)

例子:

models.py:
...
from django.db.models.query import QuerySet
...

class IcecreamManager(models.Manager):

    def get_query_set(self):
        return self.model.QuerySet(self.model)

    def __getattr__(self, attr, *args):
        try:
            return getattr(self.__class__, attr, *args)
        except AttributeError:
            return getattr(self.get_query_set(), attr, *args)


class Icecream(models.Model()):
    name = models.CharField()
    bad_threshold = models.IntegerField()
    okay_threshold = models.IntegerField()
    tasty_threshold = models.IntegerField()
    delicious_threshold = models.IntegerField()

    objects = IcecreamManager()

    class QuerySet(QuerySet):
        def name_custom_method(self, arg1, argN):
            # you must rewrite for you solution
            return self.exclude(
                            time_end__gt=now()
                        ).filter(
                            Q(...) | Q(...)
                        )

        def name_custom_method2(...)
            ...

这些应该为您提供针对您的问题构建链查询的能力。

于 2013-06-20T21:20:01.033 回答
1

这种方法怎么样?

query_arg = ['bad_threshold__lte', 'bad_threshold__lte', 'okay_threshold_3__lte', 'tasty_threshold__lte', 'delicious_threshold__lte']

Q(**{query_arg[int(threshold) - 1]: user.profile.taste_tolerance})
于 2013-06-21T03:40:49.210 回答