简体   繁体   中英

select in (select ..) using ORM django

How can I make a query

select  name where id in (select id from ...)

using Django ORM? I think I can make this using some loop for for obtain some result and another loop for, for use this result, but I think that is not practical job, is more simple make a query sql, I think that make this in python should be more simple in python

I have these models:

class Invoice (models.Model):
    factura_id = models.IntegerField(unique=True)       
    created_date = models.DateTimeField()
    store_id = models.ForeignKey(Store,blank=False)

class invoicePayments(models.Model):
    invoice = models.ForeignKey(Factura)
    date =  models.DateTimeField()#auto_now = True)
    money = models.DecimalField(max_digits=9,decimal_places=0)

I need get the payments of a invoice filter by store_id,date of pay. I make this query in mysql using a select in (select ...) . This a simple query but make some similar using django orm i only think and make some loop for but I don't like this idea:

invoiceXstore = invoice.objects.filter(local=3)

for a in invoiceXstore:
    payments = invoicePayments.objects.filter(invoice=a.id,
                                              date__range=["2016-05-01", "2016-05-06"])

You can traverse ForeignKey relations using double underscores ( __ ) in Django ORM. For example, your query could be implemented as:

payments = invoicePayments.objects.filter(invoice__store_id=3, 
                                          date__range=["2016-05-01", "2016-05-06"])

I guess you renamed your classes to English before posting here. In this case, you may need to change the first part to factura__local=3 .

As a side note, it is recommended to rename your model class to InvoicePayments (with a capital I ) to be more compliant with PEP8 .

Your mysql raw query is a sub query.

select  name where id in (select id from ...)

In mysql this will usually be slower than an INNER JOIN (refer : [ http://dev.mysql.com/doc/refman/5.7/en/rewriting-subqueries.html] ) thus you can rewrite your raw query as an INNER JOIN which will look like 1 .

SELECT ip.* FROM invoicepayments i INNER JOIN invoice i ON 
ip.invoice_id = i.id

You can then use a WHERE clause to apply the filtering.

The looping query approach you have tried does work but it is not recommended because it results in a large number of queries being executed. Instead you can do.

InvoicePayments.objects.filter(invoice__local=3, 
                                      date__range=("2016-05-01", "2016-05-06"))

I am not quite sure what 'local' stands for because your model does not show any field like that. Please update your model with the correct field or edit the query as appropriate.

To lean about __range see this https://docs.djangoproject.com/en/1.9/ref/models/querysets/#range

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM