Home > Back-end >  Queryset Many to many 'ManyRelatedManager' object is not iterable
Queryset Many to many 'ManyRelatedManager' object is not iterable

Time:02-23

I'm using Forms to filter the choices of a many to many relationship to only show the ones following a queryset. This is how my Form looks like

class ContractAdminForm(forms.ModelForm):
    class Meta:
      model = Contract
      fields = '__all__'

    def __init__(self, *args, **kwargs):
        super(ContractAdminForm, self).__init__(*args, **kwargs)
        self.fields['client_year_periods'].queryset =ClientYearPeriod.objects.filter(
              Q(contract_id__isnull=True) | Q(contract_id=self.instance.id) &
              Q(client__in=self.instance.client_entity.all()))

Error: 'ManyRelatedManager' object is not iterable The issue is being caused by Q(client__in=self.instance.client_entity))

I need to filter the model years using the client legal model that is connected to Client Ops.

See here how is it built

enter image description here

Models

class ClientEntity(models.Model):
    name = models.CharField(max_length=350, verbose_name='Client Name')
    countries = models.ManyToManyField(Country, blank=True)
    operations_code = models.ManyToManyField(Client)

class ClientYearPeriod(models.Model):
    client = models.ForeignKey(Client, on_delete=models.PROTECT, null=True)
    [...]

class Contract (models.Model):
   client_entity= models.ManyToManyField(ClientLegal)
   client_year_periods = models.ManyToManyField(ClientYearPeriod, blank=True)
   [...]


class Client(models.Model):
    code = models.CharField(max_length=3, verbose_name='Client Code')
    name = models.CharField(max_length=250, unique=True)
   

Expected Result

This contract has selected the client Someone

enter image description here

In the client Entity model it is related to Client = BEM

enter image description here

Here it should only show the ones Client: BEM Once it is saved (not when creating the contract as the client selected above it's not saved yet)

enter image description here

CodePudding user response:

The client__in=… expects a QuerySet, self.instance.client_entity is a manager, not a QuerySet.

But you need to make a QuerySet of Clients, so:

class ContractAdminForm(forms.ModelForm):
    
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.fields['client_year_periods'].queryset = ClientYearPeriod.objects.filter(
            Q(contract_id__isnull=True) |
            Q(contract_id=self.instance.id) &
            Q(client__in=Client.objects.filter(cliententity__contract=self.instance).distinct())
        )
    
    class Meta:
        model = Contract
        fields = '__all__'
  • Related