shanemgrey
shanemgrey

Reputation: 2378

How to filter a manytomany field before using to compare to another list for filtering the parent model

I need to filter results for records of individuals such that only users who are members of a program that has a non-expired release of information from the individual.

Example:

  1. User Sam is a member of a program called FoodDelivery.
  2. Individual Mike has signed a release of information authorizing members of the FoodDelivery program to see his home address.
  3. The release is good for one year from signing.

When Sam goes to list all the individuals he has access to through the FoodDelivery program, Mike should initially show up in a search.

A release is expired when expiration_date__lte='today' When the Release expires, Mike should no longer show up.

I've got it working to the point where users are shown only the individual records which have any release listing the user's program as authorized. But the expiration_date is ignored, essentially making the release indefinite.

How can I filter that list of released programs to only those where the release isn't expired? so I can use that list to match with the user programs?

``` python # simplified code for the relevant classes.

class UserProfile(models.Model):
    user = models.OneToOneField(User, on_delete=models.CASCADE, related_name="user_profile")
    program_list = models.ManyToManyField('Program', blank=True,)


class Program(models.Model):
    name = models.CharField(max_length=100, blank=True, default='')
    individual_list = models.ManyToManyField(
        'Individual',
        related_name='program_individual_list',
        through='ReleaseAuthorization',
        blank=True
    )

class Individual(models.Model):
    name = models.CharField(max_length=100, blank=True, default='')
    authorized_program_list = models.ManyToManyField(
        'Program',
        related_name='individual_authorized_program_list',
        through='ReleaseAuthorization',
        blank=True
    )

class ReleaseAuthorization(models.Model):
    individual = models.ForeignKey(
        Individual,
        related_name="release_authorization_individual",
        on_delete=models.CASCADE
    )
    program = models.ForeignKey(
        Program,
        related_name="release_authorization_program",
        on_delete=models.CASCADE
    )
    expiration_date = models.DateField()


class IndividualViewSet(model.ModelViewSet):
    model = Individual
    queryset = Individual.objects.order_by('id').distinct('id')
    serializer_class = IndividualSerializer
    filter_backends = (filters.SearchFilter, DjangoFilterBackend)
    action_serializers = {
        'list': IndividualListSerializer,
    }
    filter_fields = ('id', 'household', 'deceased')
    search_fields = ('first_name','last_name','dob')

    def get_queryset(self):
        user = self.request._user
        user_agency_program_list = user.user_profile.program_list
        user_program_list = [val.id for val in user_agency_program_list.order_by('id')]

        q = Q()
        q &= Q(created_by=user) # Allow if the record was created by the current user
        q |= Q(authorized_program_list__in=user_program_list) # Allow if there is a match between the list of authorized programs and the user programs

        # q |= Q(authorized_program_list.filter(expiration_date__lte=datetime.Date())__in=user_program_list) # Invalid Syntax, but shows what I'm trying to do

        queryset = Individual.objects.filter(q).distinct('modified_at','id')

        return queryset

```

Upvotes: 0

Views: 152

Answers (1)

Alessio Ferri
Alessio Ferri

Reputation: 345

So if i get your question right you want to show all Individuals that don't have expired the release, so you have to do:

Individual.objects.filter(release_authorization_individual__expiration_date__gt='today')

where gt stands for greater than if you need it you can use lt (less than), lte(less then or equal), gte(greater than or equal) is all in the documentation

Upvotes: 1

Related Questions