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
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
In the client Entity model it is related to Client = BEM
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)
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 Client
s, 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__'