How can I search the choice field using display name?
Sorry to create a duplicated issue in the example page.
I want to query the item from the database using django SmallIntegerField
. The code I used is
Here is the class defination:
class Equipment(models.Model):
asset_status = (
(0, 'online'),
(1, 'offline'),
(2, 'unknown'),
(3, 'wrong'),
(4, 'x'),
)
status = models.SmallIntegerField(
choices=asset_status, default=0, verbose_name='Device Status')
The query code I used is
def filter_queryset(self, qs):
sSearch = self.request.GET.get('search[value]', None)
print(sSearch)
if sSearch:
qs = qs.filter(Q(status__icontains=sSearch))
return qs
I want to query this column by 'online', 'offline' and so on. Do you know how to do this?
The reference I have searched are
https://stackoverflow.com/questions/41054755/search-choice-field-by-the-name-in-django-python
I also see the Choices
API in
https://django-model-utils.readthedocs.io/en/latest/utilities.html#choices
But there is no Q
. I am not sure whether it works. Could you please tell me about this?
And I searched for a method called get_FOO_display
, but I don't think it can be solved. Neither did I think it can be combined with Q
.
Thanks
Comments (2)
-
-
repo owner - changed status to invalid
Please use the solution suggested by @Benjamin Riddell (thanks Benjamin). This is not directly related to django-datatables-view so I'm closing this as invalid.
- Log in to comment
There are 2 solutions that I can suggest. I don’t think this is particularly relevant to django-datatables-view, rather it is more just the how you’re handling Django instead. Your filter is going to be ran against the database so it needs to use the values that are in the database. The database does not store the human-readable name but rather it stores the integer.
My first recommendation is that you try and follow the MVC pattern that Django follows. When writing your code, keep your values and their human-readable names localaised. So in your current situation, I would not submit the human-readable name in the request. I would instead submit the actual value. So your input field that is making the request would look more like:
This can be done in the template with ease so that choices only need to be updated once in the right place. I would suggest reading up on using choices in forms with Django. (Sorry I don’t have time to find the specific readings but it does exist in their documentation.)
With this solution, when the request is made, the integer value will get sent instead. The integer value would
If you don’t want to do my first recommendation. Then you can match the string value made in the request, to the integer value of the choice. This can be done with dict comprehension.
reversed_asset_status = {human_name.lower(): value for value, human_name in Equipment.asset_status}
Your query code would use this line instead
qs = qs.filter(Q(status=reversed_asset_status(sSearch.lower())))
Please note that the first recommendation is actually tidier and far more extensible than the latter. Though the second option looks like you only need to change 2 lines of code. The above option means you don't need to override the
filter_queryset
function.