简体   繁体   中英

Filter many to many field in django

I'm having trouble trying to get a query set.

I have:

class RangeDate(models.Model):
    start_date = models.DateTimeField(_("Start Date"))
    end_date = models.DateTimeField(_("End Date"))


class Product(models.Model):
    start_end_dates = models.ManyToManyField(RangeDate)

So im trying to get all the products. And only show the RangeDates that the start date is greater than datetime.now(). I don't know if a queryset can give that result or if i need to treat them in a cycle.

Also i need to order the dates in the products

Hope you can help me. Thanks in advance.

EDIT 1 So i make this, but i think that it might be a better way:

product = Product.objects.filter(start_end_dates__start_date__gt=
                                   datetime.now())

but if the product has one greater and one lower than now it also gives me the product and it gives me repeated products so i use:

product = Product.objects.filter(start_end_dates__start_date__gt=
                                   datetime.now()).distinct()

then in the model i made a function for checking the dates:

def is_older_than_now(self):
    return self.start_date < datetime.now()

and i call it in the template:

 {% if not date.is_older_than_now %}
     ---
 {%endif}

and a filter tag for ordering:

{% for date in product.start_end_dates.all|order_by:"start_date" %}
    ---
{% endfor %}

You are probably looking for the __gt modifier. ManyToManyField s can be queried and filtered like regular fields, and filtering on a field in the related model just requires a dunderscore ( __ ).

This query should work to get all Products with a start date after today:

import datetime
Product.objects.filter(start_end_dates__start_date__gt=datetime.now())

Based on the edit if you need a list of Products that have start dates that are all after 'now', then thats just a matter of some boolean fiddling:

A "product that has all ranges with a start greater than now" is equivalent to "a product that has does not have any ranges less than now". Which can be done with a Q object :

from django.db.models import Q
Product.objects.filter(~Q(start_end_dates__start_date__lte=datetime.now()))

The section ~Q(...) is in effect saying "not this query (the ~ )", so its saying:

Filter Products by those that have not got a start_end_dates with a start_date less than today.

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