Django 1.11:使用Q组合QuerySet的字段

时间:2018-01-08 23:48:28

标签: python django datatable

我使用DataTable插件呈现" nanas"的参考列表。 (保姆的西班牙人)。现在我可以过滤:nana的nombre(名字)或引用的nombre(名字)。

我希望过滤nana's nombre + nana's apellido_paterno

这样做不起作用(返回空表,即使应该匹配):

if search_value:
    queryset = queryset.filter(
        Q(nana__nombre__icontains=search_value) & Q(nana__apellido_paterno__icontains=search_value),
        Q(nana__numero_de_documento__exact=search_value)
    )

型号:

class Referencia(models.Model):
    nombre_apellido = models.CharField(blank=False, null=False, max_length=200)
    telefono = models.CharField(blank=False, null=False, max_length=15)
    correo = models.EmailField(blank=True, null=True)
    direccion = models.TextField(blank=True, null=True)
    estado_referencia = models.IntegerField(blank=False, null=False, choices=ESTADO_REFERENCIA, default=0)
    nana = models.ForeignKey(Nana)
    comentario = models.CharField(blank=True, null=True, max_length=400)


def query_referencia_by_args(**kwargs):
    draw = int(kwargs.get('draw', None)[0])
    length = int(kwargs.get('length', None)[0])
    start = int(kwargs.get('start', None)[0])
    search_value = kwargs.get('search[value]', None)[0]
    order_column = kwargs.get('order[0][column]', None)[0]
    order = kwargs.get('order[0][dir]', None)[0]

    order_column = ORDER_COLUMN_CHOICES[order_column]
    # django orm '-' -> desc
    if order == 'desc':
        order_column = '-' + order_column

    queryset = Referencia.objects.all()
    total = queryset.count()

    if search_value:
        queryset = queryset.filter(
            # Q(nombre_apellido__icontains=search_value) |
            Q(nana__nombre__icontains=search_value) | Q(nana__apellido_paterno__icontains=search_value) |
            Q(nana__numero_de_documento__exact=search_value)
        )

    count = queryset.count()
    queryset = queryset.order_by(order_column)[start:start + length]
    return {
        'items': queryset,
        'count': count,
        'total': total,
        'draw': draw
    }

编辑1:

尝试完syntech答案后,我修改了我的def,但没有过滤任何东西:

def query_referencia_by_args(**kwargs):
    draw = int(kwargs.get('draw', None)[0])
    length = int(kwargs.get('length', None)[0])
    start = int(kwargs.get('start', None)[0])
    search_value = kwargs.get('search[value]', None)[0]
    order_column = kwargs.get('order[0][column]', None)[0]
    order = kwargs.get('order[0][dir]', None)[0]

    order_column = ORDER_COLUMN_CHOICES[order_column]
    # django orm '-' -> desc
    if order == 'desc':
        order_column = '-' + order_column

    # queryset = Referencia.objects.all()


    queryset = Referencia.objects.annotate(combined_name=Concat(
        'nana__nombre',
        V(' '),
        'nana__apellido_paterno',
        output_field=models.CharField()
    )
    )

    total = queryset.count()

    if search_value:
        queryset.filter(combined_name__icontains=search_value)

        # queryset = queryset.filter(
        #     # Q(nombre_apellido__icontains=search_value) |
        #     Q(nana__nombre__icontains=search_value) | Q(nana__apellido_paterno__icontains=search_value) |
        #     Q(nana__numero_de_documento__exact=search_value)
        # )

    count = queryset.count()
    queryset = queryset.order_by(order_column)[start:start + length]
    return {
        'items': queryset,
        'count': count,
        'total': total,
        'draw': draw
    }

1 个答案:

答案 0 :(得分:0)

您可以通过过滤注释来获得此结果。

首先,为字段combined_name创建一个注释,该字段表示由空格分隔的nana__nombrenana__apellido_paterno的组合。我们使用objects.annotate Concat函数执行此操作。

from django.db.models.functions import Concat
from django.db.models import Value as V

qs = Referencia.objects.annotate(combined_name=Concat(
                                               'nana__nombre',
                                               V(' '),
                                               'nana__apellido_paterno',
                                               output_field=models.CharField()
                                               )
                                 )

我们可以使用我们注释的combined_name“字段”来过滤此qs以获得结果。使用我描述的场景,让我们测试一下......

search_value = 'Alice Smith'
results = qs.filter(combined_name__icontains=search_value)

a = results.first()
print(a.nana.nombre)
# 'Alice'
print(a.nana.apellido_paterno)
# 'Smith'

编辑:转录错误有一个小错误。