Using ModelChoiceFilter and ManyToMany — help overriding value/label

184 views
Skip to first unread message

Paul Schreiber

unread,
Jan 13, 2021, 11:25:16 PM1/13/21
to django...@googlegroups.com
I have three models:

class IntakeCase:
name  = models.CharField(max_length=200)
record_request_status = models.CharField(max_length=4, null=True, choices=list(RECORD_REQUEST_STATUS))

class Organization(models.Model):
name     = models.CharField(max_length=200, null=True)
org      = models.TextField(max_length=300, null=True)
obsolete = models.BooleanField(default=False, null=True)
def __str__(self):
name = '%s (%s)' % (self.name, self.org)
if self.obsolete:
name = '%s (OBS)' % (name)
return name

class Agency:
intake_case  = models.ForeignKey(IntakeCase, on_delete=models.CASCADE, related_name='agencies', null=True)
organization = models.ForeignKey(Organization, on_delete=models.CASCADE)

And a filter like so:
class IntakeCaseFilter(django_filters.FilterSet):
name = django_filters.CharFilter(field_name='name', lookup_expr='icontains')
agencies__organization__name = django_filters.ModelChoiceFilter(queryset=Organization.objects.all(), to_field_name='name')

class Meta:
model = IntakeCase
fields = [ 'name', 'record_request_status', 'agencies__organization__name' ]

My filter form looks like so:



Looking at the HTML source for the agencies__organization__name popup, I see this:
   <option value=“Sample Dept">Sample Dept (SAMPLE PD)</option>


The _value_ is set to name (from to_field_name), but the label is set to the value of __str__ on the Organization model. The generated SQL also uses the __str__ value, which means nothing matches.

SELECT COUNT(*) AS "__count" FROM "myapp_intakecase" INNER JOIN "myapp_agency" ON ("myapp_intakecase"."id" = "myapp_agency"."intake_case_id") INNER JOIN "myapp_organization" ON ("myapp_agency"."organization_id" = "myapp_organization"."id") WHERE "myapp_organization"."name" = 'Sample Dept (SAMPLE PD)'; args=(‘Sample Dept (SAMPLE PD)',)

What I want is this:

SELECT COUNT(*) AS "__count" FROM "myapp_intakecase" INNER JOIN "myapp_agency" ON ("myapp_intakecase"."id" = "myapp_agency"."intake_case_id") INNER JOIN "myapp_organization" ON ("myapp_agency"."organization_id" = "myapp_organization"."id") WHERE "myapp_organization"."name" = 'Sample Dept'; args=(‘Sample Dept',)


If I override __str__ to always return self.name, this “works” (giving the latter SQL).

However, I would like to keep my custom value of Organization’s __str__ for display purposes.

How can I alter the filter to use the name field's value instead of the value of __str__? Alternately, if there’s a better way to do this, happy to hear it.



thanks.
Paul
Reply all
Reply to author
Forward
0 new messages