Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/vba/14.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/scala/19.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Django使用复杂的Q查找按字段获取下一个字段_Django_Django Views_Django Queryset_Django Q - Fatal编程技术网

Django使用复杂的Q查找按字段获取下一个字段

Django使用复杂的Q查找按字段获取下一个字段,django,django-views,django-queryset,django-q,Django,Django Views,Django Queryset,Django Q,在为Django模块创建前端时,我在Django内核中遇到了以下问题: 为了显示从模型查询到下一个/上一个对象的链接,我们可以使用模型实例的:get_next_by_FIELD()或get_previous_by_FIELD()。其中字段是DateField或DateTimeField类型的模型字段 让我们用一个例子来解释它 显示鞋的列表的视图,不包括尺寸等于4的鞋: def list_shoes(request): shoes = Shoe.objects.exclude(size=4

在为Django模块创建前端时,我在Django内核中遇到了以下问题:

为了显示从模型查询到下一个/上一个对象的链接,我们可以使用模型实例的:get_next_by_FIELD()或get_previous_by_FIELD()。其中字段是DateField或DateTimeField类型的模型字段

让我们用一个例子来解释它 显示鞋的列表的视图,不包括尺寸等于4的鞋:

def list_shoes(request):
    shoes = Shoe.objects.exclude(size=4)

    return render_to_response(request, {
        'shoes': shoes
    })
让下面的视图显示一只鞋和相应的 链接到上一双鞋和下一双鞋

def show_shoe(request, shoe_id):
    shoe = Shoe.objects.get(pk=shoe_id)

    prev_shoe = shoe.get_previous_by_created()
    next_shoe = shoe.get_next_by_created()

    return render_to_response('show_shoe.html', {
        'shoe': shoe,
        'prev_shoe': prev_shoe,
        'next_shoe': next_shoe
    })
现在我遇到了这样的情况:show_shoe视图显示指向上一个/下一个的链接,而不考虑鞋的尺寸。但事实上我只想要尺码不是4的鞋子。 因此,我尝试使用get_(previous | next)_by_created()方法的**kwargs参数来过滤掉不需要的鞋子,如文档所述:

这两种方法都将使用模型的默认管理器执行查询。如果您需要模拟自定义管理器使用的筛选,或者希望执行一次性自定义筛选,这两种方法都可以接受 可选关键字参数,应采用字段查找中描述的格式

编辑:注意“应该”这个词,因为这样(大小=4)也应该起作用,但它不起作用

实际问题 正在使用查找大小进行筛选

def show_shoe(request, shoe_id):
    ...
    prev_shoe = shoe.get_previous_by_created(size__ne=4)
    next_shoe = shoe.get_next_by_created(size__ne=4)
    ...
。。。不起作用,它抛出字段错误:无法将关键字“size\u ne”解析到字段中

然后我尝试使用一个使用Q对象的否定:

from django.db.models import Q

def show_shoe(request, shoe_id):
    ...
    prev_shoe = shoe.get_previous_by_created(~Q(size=4))
    next_shoe = shoe.get_next_by_created(~Q(size=4))
    ...
。。。也不起作用,抛出类型错误:_get_next_或_previous_by_FIELD()为参数“FIELD”获取了多个值

因为get_u(previous | next)by_创建的方法只接受**kwargs

def my_get_next_or_previous_by_FIELD(self, field, is_next, *args, **kwargs):
    """
    Workaround to call get_next_or_previous_by_FIELD by using complext lookup queries using
    Djangos Q Class. The only difference between this version and original version is that
    positional arguments are also passed to the filter function.
    """
    if not self.pk:
        raise ValueError("get_next/get_previous cannot be used on unsaved objects.")
    op = 'gt' if is_next else 'lt'
    order = '' if is_next else '-'
    param = force_text(getattr(self, field.attname))
    q = Q(**{'%s__%s' % (field.name, op): param})
    q = q | Q(**{field.name: param, 'pk__%s' % op: self.pk})
    qs = self.__class__._default_manager.using(self._state.db).filter(*args, **kwargs).filter(q).order_by('%s%s' % (order, field.name), '%spk' % order)
    try:
        return qs[0]
    except IndexError:
        raise self.DoesNotExist("%s matching query does not exist." % self.__class__._meta.object_name)
实际解决方案 由于这些实例方法使用了,我将其更改为使用*args接受位置参数,并将它们传递给过滤器,如**kwargs

def my_get_next_or_previous_by_FIELD(self, field, is_next, *args, **kwargs):
    """
    Workaround to call get_next_or_previous_by_FIELD by using complext lookup queries using
    Djangos Q Class. The only difference between this version and original version is that
    positional arguments are also passed to the filter function.
    """
    if not self.pk:
        raise ValueError("get_next/get_previous cannot be used on unsaved objects.")
    op = 'gt' if is_next else 'lt'
    order = '' if is_next else '-'
    param = force_text(getattr(self, field.attname))
    q = Q(**{'%s__%s' % (field.name, op): param})
    q = q | Q(**{field.name: param, 'pk__%s' % op: self.pk})
    qs = self.__class__._default_manager.using(self._state.db).filter(*args, **kwargs).filter(q).order_by('%s%s' % (order, field.name), '%spk' % order)
    try:
        return qs[0]
    except IndexError:
        raise self.DoesNotExist("%s matching query does not exist." % self.__class__._meta.object_name)
并称之为:

...
prev_shoe = shoe.my_get_next_or_previous_by_FIELD(Shoe._meta.get_field('created'), False, ~Q(state=4))
next_shoe = shoe.my_get_next_or_previous_by_FIELD(Shoe._meta.get_field('created'), True, ~Q(state=4))
...
终于做到了

现在我想问你一个问题 有没有更简单的方法来处理这个问题?是否应该让shoe.get_previous_by_created(size_une=4)按预期工作,或者我应该将此问题报告给Django的同事,希望他们接受我的_get_next_或_previous_by_FIELD()修复

环境:Django 1.7,尚未在1.9上对其进行测试,但_get_next_或_previous_by_FIELD()的代码保持不变

编辑:确实,使用Q对象的复杂查找不是“字段查找”的一部分,而是filter()和exclude()函数的一部分。当我认为get_next_by_字段也应该接受Q对象时,我可能是错的。但由于所涉及的更改非常少,并且使用Q对象的优势很高,所以我认为这些更改应该向上游进行

标记:django、复杂查找、查询、按字段获取下一个、按字段获取上一个


(在这里列出标记,因为我没有足够的声誉。)

我怀疑您首先尝试的方法只对您下一个get_所基于的字段使用lookup arg。例如,这意味着您将无法从get_next_by_created()方法访问size字段

编辑:你的方法要有效得多,但要回答你关于Django问题的问题,我认为一切都按预期的方式进行。您可以提供其他方法,如您的方法,但现有的get_next_by_字段正在按照文档中所述工作

您已经用一种工作方法解决了这个问题,我想这是可以的,但是如果您想减少开销,您可以尝试一个简单的循环:

def get_next_by_field_filtered(obj, field=None, **kwargs):

    next_obj = getattr(obj, 'get_next_by_{}'.format(field))()

    for key in kwargs:
        if not getattr(next_obj, str(key)) == kwargs[str(key)]:
            return get_next_by_field_filtered(next_obj, field=field, **kwargs)

    return next_obj
这不是很有效,但这是一种你想做的事情

希望这有帮助

关于,您可以创建并使用它:

.get_next_by_created(size__ne=4)

因为这是我的第一个问题,有什么改进的建议吗?是的,循环也可以,但我不太喜欢,但你的解决方案看起来更好。而且我不确定循环的计算/db开销是否比使用修改的my_get_next_或_previous_by_字段低,因为每次调用get_next_by_字段都需要访问数据库。这就是为什么我想使用size_ne或Q对象来解决这个问题,这样只需一次DB访问就可以获得所需的结果。是的,你完全正确,你的方法非常有效:)创建一个自己的查找工作!但为什么不能使用开箱即用的尺寸?因为它“应该”的行为类似于其他字段查找。因为默认情况下没有
ne
查找。