2010-07-21 29 views
18

Quiero ejecutar una actualización de Django a través del ORM que se ve algo como esto:¿Puedo usar objetos Django F() con concatenación de cadenas?

MyModel.objects.filter(**kwargs).update(my_field=F('my_other_field')+'a string') 

Esto hace que MySQL para lanzar una excepción. ¿Hay alguna forma de hacerlo sin escribir SQL sin formato?

Respuesta

25

Lo que sucede es que Django está pasando el '+' a SQL, pero SQL no permite el uso de '+' para la concatenación, por lo que intenta sumar numéricamente. Si usa un número entero en lugar de 'una cadena', funciona en el sentido de que agrega el valor entero de my_other_field a su variable.

Es discutible si esto es un error. El documentation for F() objects en las consultas de búsqueda afirma:

Django soporta el uso de la suma, resta, multiplicación, división y módulo aritmético con F() objetos

por lo que podría argumentarse que no se debe tratar de Úselo para actualizar con cadenas. Pero eso ciertamente no está documentado, y el mensaje de error "Valor DOBLE incorrecto" no es muy útil. Abriré un boleto.

+0

Gracias por la respuesta detallada – Zach

+0

En SQLite es aún menos útil: ¡simplemente establece el texto en "0"! – boxed

24

tuve un problema similar; básicamente quería concatenar dos campos para obtener el nombre completo de un usuario. Lo tengo resuelto de esta manera (pero hay que decir que yo estaba usando Postgres):

from django.db.models.functions import Concat 
from django.db.models import F, Value, CharField 

AnyModel.objects.filter(**kwargs).annotate(full_name=Concat(F('model__user_first_name'), Value(' '), F('model__user_last_name'), output_field=CharField())) 

donde, F ('...') evalúa su argumento como una consulta, por lo que puede consultar un campo de el modelo en sí, o abarque todos los modelos como lo haría en filter/get, mientras que Value ('...') evalúa su argumento literalmente (en mi caso necesitaba un espacio para colocar entre first_name y last_name), y output_field = ... especifica el tipo del campo anotado (yo quería ser un CharField). Para obtener más información, puede leer Django docs about Concat

Espero que sea útil para alguien por ahí. Cheers

+0

Esta es una respuesta excelente que funciona como se esperaba. – ihhcarus

+0

Esta es una gran respuesta que funciona como se esperaba. –

Cuestiones relacionadas