Reputation: 4137
I wrote some instructions in order to extract data from my database.
I have two values; a city name and a keyword, which are attributes of Address
and Museum
:
class Museum(models.Model):
id = models.AutoField(primary_key=True)
name = models.CharField(max_length=200)
address = models.ForeignKey(Address)
description = models.CharField(max_length=200)
class Address(models.Model):
id = models.AutoField(primary_key=True)
streetAddress = models.CharField(max_length=200)
city = models.CharField(max_length=200)
Now I am receiving two optional parameters: a city and and a keyword. I want to filter out museums according to such city (exact match) AND such keyword (partial match in name OR description)
This is what I ended up writing:
if city is not None and keyword is None:
city_data = Address.objects.all().filter(city=city)
museum_list = Museum.objects.all().filter(address__in=city_data)
elif city is None and keyword is not None:
museum_list = Museum.objects.all().filter(
Q(name__contains=keyword) | Q(description__contains=keyword)
)
elif city is not None and keyword is not None:
city_data = Address.objects.all().filter(city=city)
museum_list = Museum.objects.all().filter(
Q(address__in=city_data) & (
Q(name__contains = keyword) | Q(description__contains=keyword)
)
)
else:
museum_list = Museum.objects.all()
I don't like this code, because I am accounting for all possible combinations. How can I use Django filtering to improve such code to something like:
results = Museum.objects.all()
if city not null
results = results.filterByAddress_City
if keyword not null
results = results.filterByKeywordLikeNameOrLikeDescription
Thanks.
Upvotes: 0
Views: 130
Reputation: 599956
Queries are composable, so you can pretty much do exactly what you state in your pseudocode.
results = Museum.objects.all()
if city:
results = results.filter(address__city=city)
if keyword:
results = results.filter(Q(name__contains = keyword) | Q(description__contains = keyword))
Upvotes: 2