[pyar] Python - Django - select_related
Jose Luis
joseluiszanotti en gmail.com
Lun Mayo 30 10:46:16 ART 2016
Actualización...
usando este RAW bajo de 1,9 segundos a 170ms la respuesta :D
@staticmethod
def get_context_data(self, request):
product_info = []
category_id = request.GET['category_id']
main_products = ProductMain.objects.raw(
'SELECT A.id, A.name, A.model, A.status, D.price, D.stock from
products_productmain A '
'INNER JOIN products_product B on A.id = B.product_main_id '
'INNER JOIN ( SELECT product_id, MAX(id) as var_id FROM
products_productvariation GROUP BY product_id ) as C '
'on B.id = C.product_id '
'INNER JOIN products_productvariation D on D.id = C.var_id '
'WHERE A.main_category_id = ' + category_id
)
for main_product in main_products:
product_info.append({
'status': main_product.status,
'id': main_product.id,
'name': main_product.name,
'model': main_product.model,
'stock': main_product.stock,
'price': main_product.price,
'ml_category_id': main_product.ml_category_id,
})
return product_info
El 30/05/16 a las 02:20, fisa escribió:
> Detalle interesante: veo que usas mucho .values() en las queries. Lo
> estás haciendo como optimización?
> Haciendo eso obtenés dicts en lugar de instancias de los modelos, los
> dicts son un poco más "ásperos", las instancias son bastante más
> manejables.
> Si lo que querés es justamente evitar que se creen instancias por
> temas de performance (te estás trayendo miles de cosas, etc), tiene
> sentido usar values. Pero si no hay un problema de performance, no veo
> por qué hacerlo, siendo que hace todo el resto del código un poco más feo.
> Si no querés traerte toooodos los campos, igual podés traerte
> instancias del modelo solo queryando (?) los campos que te interesan
> mediante el uso de only().
> (Modelo.objects.filter(blablabla).only('campo1_que_quiero', 'campo2...') )
>
> On Sun, May 29, 2016 at 10:35 PM Jose Luis <joseluiszanotti en gmail.com
> <mailto:joseluiszanotti en gmail.com>> wrote:
>
> :/
>
>
> El 29/05/16 a las 22:31, fisa escribió:
>> My bad! Pensé que main_product era una instancia de ProductMain,
>> pero mirando veo que no, es un dict que sale de esa query con
>> values antes.
>> Eso que te dije es para cuando lo que tengas sean instancias de
>> los modelos, mi error :)
>>
>> Saludos!
>>
>> On Sun, May 29, 2016 at 10:16 PM Jose Luis
>> <joseluiszanotti en gmail.com <mailto:joseluiszanotti en gmail.com>> wrote:
>>
>> Fisa, estuve intentando lo que decis de no usar el ID, pero
>> me tira este error "TypeError: int() argument must be a
>> string or a number, not 'dict'"
>>
>> en que parte decis q use
>> Product.objects.values('id').get(product_main=main_product) ?
>> dentro del loop?
>>
>> Abrazo
>>
>>
>>
>> El 29/05/16 a las 21:33, fisa escribió:
>>> Dos detalles que noto:
>>>
>>> 1) No hace falta que uses los _id a mano para comparar, de
>>> hecho no es recomendable que lo hagas. Podés hacer
>>> directamente esto:
>>> Product.objects.values('id').get(product_main=main_product)
>>> 2) Veo que Por cada ProductMain hay un solo Product, y que
>>> no todos los Product tienen ProductMain, pero siempre por
>>> cada ProductMain asumís que existe ese único Product
>>> apuntando a él. Qué es lo que te llevó a poner la foreign
>>> key en Product y no al revés? me suena a que si todo
>>> ProductMain tiene un único Product asociado, y no a la
>>> inversa, entonces es una foreign key que va en ProductMain,
>>> no? Hacerlo de esa forma además te ahorraría/simplificaría
>>> un poco las queries (podrías hacer directamente
>>> ProductMain.filter(...).select_related(relacion_a_product) y
>>> te traerías todos los ProductMain con sus Product en una
>>> sola query re simple).
>>>
>>> Saludos!
>>>
>>>
>>>
>>> On Sun, May 29, 2016 at 9:13 PM Jose Luis
>>> <joseluiszanotti en gmail.com
>>> <mailto:joseluiszanotti en gmail.com>> wrote:
>>>
>>> Excelente voy a probar en un rato algo parecido a eso.
>>>
>>> Lo que necesito es obtener es un dict con TODOS los
>>> ProductMain + el ultimo valor de ProductVariation de
>>> cada ProductMain . Uno de los problemas es que tengo
>>> tres tablas.
>>>
>>> para obtener el ProductVariation necesito consultar el
>>> ID en Product, lindo lio hice con las tablas me parece :D
>>>
>>>
>>>
>>>
>>>
>>> El 29/05/16 a las 20:41, Alessandro Odetti escribió:
>>>> Hola José Luis,
>>>>
>>>> si lo que querés efectivamente es obtener los
>>>> ProductVariation de una categoria de ProductMain, yo lo
>>>> haría de la siguente forma utlilizando los lookups de
>>>> Django, quizás alguno te pueda dar una mejor opción:
>>>>
>>>> category_id = request.GET['category_id']
>>>> ProductVariation.objects.values('stock',
>>>> 'price').filter(product__product_main__main_category_id=category_id)
>>>>
>>>> eso te va a dar todos los ProductVariation. Si luego
>>>> queres obtener el ultimo de cada producto deberias
>>>> hacer un distinct o algo por el estilo...
>>>>
>>>> Espero te sirva. Saludos!
>>>>
>>>>
>>>>
>>>> El 29 de mayo de 2016, 19:08, Jose Luis
>>>> <joseluiszanotti en gmail.com
>>>> <mailto:joseluiszanotti en gmail.com>> escribió:
>>>>
>>>> Hola estimados, estoy jugando desde hace una semana
>>>> con Django, y estoy migrando una app q tenía en
>>>> flask a django.
>>>>
>>>> Mientras voy escribiendo el nuevo código veo la
>>>> cantidad de cosas "fuleras" que he escrito hace
>>>> solo un par de meses, así que aprovecho para
>>>> optimizar un poco el código y los tiempos de ejecución.
>>>>
>>>> Entre las partes de optimización, estoy viendo de o
>>>> modificar la estructura de los modelos/tablas o que
>>>> alguien me oriente a usar select_related o algun
>>>> tipo de join. El problema reside en esta parte del
>>>> código.
>>>>
>>>> MODELOS
>>>> class ProductMain(models.Model):
>>>> name = models.CharField(max_length=255)
>>>> model = models.CharField(max_length=30)
>>>> description = models.TextField()
>>>> specs = models.TextField()
>>>> update_by = models.DateField(auto_now_add=True)
>>>> status = models.BooleanField()
>>>> image = models.BooleanField()
>>>> main_category =
>>>> models.ForeignKey('categories.MainCategory')
>>>>
>>>> class Product(models.Model):
>>>> code = models.CharField(max_length=30)
>>>> name = models.CharField(max_length=255)
>>>> model = models.CharField(max_length=25)
>>>> description = models.TextField(null=True)
>>>> warranty = models.IntegerField()
>>>> tax = models.IntegerField()
>>>> sales = models.IntegerField()
>>>> value = models.DecimalField(max_digits=9,
>>>> decimal_places=2)
>>>> update_by = models.DateField(auto_now_add=True)
>>>> status = models.BooleanField(default=True)
>>>> product_related =
>>>> models.ForeignKey(ProductRelated, default=None)
>>>> product_category =
>>>> models.ForeignKey(ProductCategory, default=None)
>>>> manufacturer =
>>>> models.ForeignKey('manufacturers.Manufacturer',
>>>> default=None)
>>>> supplier =
>>>> models.ForeignKey('suppliers.Supplier', default=None)
>>>> product_main = models.ForeignKey(ProductMain,
>>>> default=None)
>>>>
>>>>
>>>> class ProductVariation(models.Model):
>>>> price = models.DecimalField(max_digits=9,
>>>> decimal_places=2)
>>>> stock = models.IntegerField()
>>>> incoming = models.IntegerField()
>>>> update_by = models.DateField(auto_now_add=True)
>>>> # status = models.BooleanField(default=True)
>>>> product = models.ForeignKey(Product)
>>>>
>>>>
>>>>
>>>> class GetProducts(View):
>>>> def get(self, request):
>>>> return
>>>> JsonResponse(self.get_context_data(self, request),
>>>> safe=False)
>>>>
>>>> @staticmethod
>>>> def get_context_data(self, request):
>>>> product_info = []
>>>> category_id = request.GET['category_id']
>>>> main_products =
>>>> list(ProductMain.objects.values().filter(main_category_id=category_id))
>>>> # test_products =
>>>> list(ProductMain.objects.select_related(Product).filter(main_category_id=category_id))
>>>> # print test_products
>>>> # quit()
>>>> for main_product in main_products:
>>>> product =
>>>> Product.objects.values('id').get(product_main_id=main_product['id'])
>>>> stock_price =
>>>> ProductVariation.objects.values('stock',
>>>> 'price').filter(product_id=product['id']).last()
>>>> product_info.append(dict(main_product, **stock_price))
>>>> return product_info
>>>>
>>>> como verán hace 3 query por separados para obtener
>>>> los datos stock y price que estan en otra tabla :/
>>>>
>>>> Pueden ver la posibilidad de darme una mano (para
>>>> hacer el query en una sola linea o para
>>>> modificar/estructurar los modelos de otra forma),
>>>> estoy medio perdido.
>>>>
>>>> Gracias de antemano!
>>>> Sam
>>>>
>>>> _______________________________________________
>>>> pyar mailing list pyar en python.org.ar
>>>> <mailto:pyar en python.org.ar>
>>>> http://listas.python.org.ar/listinfo/pyar
>>>>
>>>> PyAr - Python Argentina - Sitio web:
>>>> http://www.python.org.ar/
>>>>
>>>> La lista de PyAr esta Hosteada en USLA - Usuarios
>>>> de Software Libre de Argentina - http://www.usla.org.ar
>>>>
>>>>
>>>>
>>>>
>>>> --
>>>> *- Alessandro Odetti -*
>>>>
>>>>
>>>> _______________________________________________
>>>> pyar mailing listpyar en python.org.ar <mailto:pyar en python.org.ar>
>>>> http://listas.python.org.ar/listinfo/pyar
>>>>
>>>> PyAr - Python Argentina - Sitio web:http://www.python.org.ar/
>>>>
>>>> La lista de PyAr esta Hosteada en USLA - Usuarios de Software Libre de Argentina -http://www.usla.org.ar
>>>
>>> _______________________________________________
>>> pyar mailing list pyar en python.org.ar
>>> <mailto:pyar en python.org.ar>
>>> http://listas.python.org.ar/listinfo/pyar
>>>
>>> PyAr - Python Argentina - Sitio web:
>>> http://www.python.org.ar/
>>>
>>> La lista de PyAr esta Hosteada en USLA - Usuarios de
>>> Software Libre de Argentina - http://www.usla.org.ar
>>>
>>> --
>>> --
>>> fisa - Juan Pedro Fisanotti
>>>
>>>
>>> _______________________________________________
>>> pyar mailing listpyar en python.org.ar <mailto:pyar en python.org.ar>
>>> http://listas.python.org.ar/listinfo/pyar
>>>
>>> PyAr - Python Argentina - Sitio web:http://www.python.org.ar/
>>>
>>> La lista de PyAr esta Hosteada en USLA - Usuarios de Software Libre de Argentina -http://www.usla.org.ar
>> _______________________________________________
>> pyar mailing list pyar en python.org.ar <mailto:pyar en python.org.ar>
>> http://listas.python.org.ar/listinfo/pyar
>>
>> PyAr - Python Argentina - Sitio web: http://www.python.org.ar/
>>
>> La lista de PyAr esta Hosteada en USLA - Usuarios de Software
>> Libre de Argentina - http://www.usla.org.ar
>>
>> --
>> --
>> fisa - Juan Pedro Fisanotti
>>
>>
>> _______________________________________________
>> pyar mailing listpyar en python.org.ar <mailto:pyar en python.org.ar>
>> http://listas.python.org.ar/listinfo/pyar
>>
>> PyAr - Python Argentina - Sitio web:http://www.python.org.ar/
>>
>> La lista de PyAr esta Hosteada en USLA - Usuarios de Software Libre de Argentina -http://www.usla.org.ar
>
> _______________________________________________
> pyar mailing list pyar en python.org.ar <mailto:pyar en python.org.ar>
> http://listas.python.org.ar/listinfo/pyar
>
> PyAr - Python Argentina - Sitio web: http://www.python.org.ar/
>
> La lista de PyAr esta Hosteada en USLA - Usuarios de Software
> Libre de Argentina - http://www.usla.org.ar
>
> --
> --
> fisa - Juan Pedro Fisanotti
>
>
> _______________________________________________
> pyar mailing list pyar en python.org.ar
> http://listas.python.org.ar/listinfo/pyar
>
> PyAr - Python Argentina - Sitio web: http://www.python.org.ar/
>
> La lista de PyAr esta Hosteada en USLA - Usuarios de Software Libre de Argentina - http://www.usla.org.ar
------------ próxima parte ------------
Se ha borrado un adjunto en formato HTML...
URL: <http://listas.python.org.ar/pipermail/pyar/attachments/20160530/f6248e67/attachment-0001.html>
Más información sobre la lista de distribución pyar