简体   繁体   中英

Django ORM exclude records using an array of dictionaries

I have similar code that return all entries from a table:

all_entries = Entry.objects.all()

and I have the following array:

exclusion_list = [
  {
    "username": "Tom",
    "start_date": 01/03/2019,
    "end_date": 29/02/2020,
  },
  {
    "username": "Mark",
    "start_date": 01/02/2020,
    "end_date": 29/02/2020,
  },
  {
    "username": "Pam",
    "start_date": 01/03/2019,
    "end_date": 29/02/2020,
  }
]

I want to exclude all Tom's records from "01/03/2019" to "29/02/2020", all "Mark" records from "01/02/2020" to "29/02/2020" and all Pam's record from "01/03/2019" to "29/02/2020"

I want to do that in a loop, so I believe i should do something like:

for entry in all_entries:
    filtered_entry = all_entries.exclude(username=entry.username).filter(date__gte=entry.start_date, date__lte=entry.end_date)

Is this approach correct? I am new to Django ORM. Is there a better and more efficient solution?

Thank you for your help

Yes, you can do this with a loop.

This results in a query whose WHERE-clause gets extended every cycle of your loop. But to do this, you have to use the filtered queryset of your previous cycle:

filtered_entry = all_entries

for exclude_entry in exclusion_list:
   filtered_entry = filtered_entry.exclude(username=exclude_entry.username, date__gte=exclude_entry.start_date, date__lte=exclude_entry.end_date)
Notes
  • Using the same reference of the queryset to limit the results further every loop cycle
  • To use multiple criteria connected with AND, just write multiple keyword arguments within exclude() (look into the docs [here][1])
  • Be aware, that this can result in a large WHERE-clause and maybe there are limitations of your database

So if your exclude_list is not too big, I think you can use this without concerns.

If your exclude_list grows, the best would be to save your exclusion_list in the database itself. With this the ORM can generate subqueries instead of single values. Just an example:

 exclusion_query = ExclusionEntry.objects.all().values('username') filtered = all_entries.exclude(username__in=exclusion_query)
 [1]: https://docs.djangoproject.com/en/3.1/topics/db/queries/#retrieving-specific-objects-with-filters

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