Add a overall search to a Admin class

I have this class ShiftAdmin:

class ShiftAdmin(admin.ModelAdmin):
    list_display = ['id', 'start_date', 'formatted_start_time', 'formatted_end_time', 'shift_title', 'site', 'user', 'status']
    actions = ['delete_selected', 'export_selected_to_csv']


    def delete_selected(self, request, queryset):
        queryset.delete()

    delete_selected.short_description = "Delete selected"

    def export_selected_to_csv(self, request, queryset):
        response = HttpResponse(content_type='text/csv')
        response['Content-Disposition'] = 'attachment; filename="shifts.csv"'

        writer = csv.writer(response, delimiter=';')
        writer.writerow(['ID', 'Start Date', 'Start Time', 'End Time', 'Shift Title', 'Site ID', 'User ID', 'Status'])
        for shift in queryset:
            writer.writerow([shift.id, shift.start_date, shift.start_time.strftime('%H:%M'), shift.end_time.strftime('%H:%M'),
                             shift.shift_title, shift.site_id, shift.user_id, shift.status])

        return response

    export_selected_to_csv.short_description = "Export selected to CSV"

    def formatted_start_time(self, obj):
        return obj.start_time.strftime('%H:%M')

    formatted_start_time.short_description = 'Start Time'

    def formatted_end_time(self, obj):
        return obj.end_time.strftime('%H:%M')

    formatted_end_time.short_description = 'End Time'


admin.site.register(Shift, ShiftAdmin)

I would like to add a search option that looks in all the fields. The date format should be 12-02-2023

Would that be possible?

EG: search_fields = [‘id’, ‘start_date’, ‘start_time’, ‘end_time’, ‘shift_title’, ‘site__site_name’, ‘user__first_name’,
‘user__last_name’]

You need to use pipes and Q.

from django.db.models import Q

filter_one = Model.objects.all().filter()

results = Model.objects.filter( Q(start_date__icontains=filter_one | Q(start_time__icontains=filter_one)) Then keeping adding pipes and Q’s.

Let me know if that works or helped.

Works! Thanks for this! I need one adjustment. I want to input the dat like 12-02-2023. It now only works with 2023-02-12 (as stored in the database). Is there a way to accept 12-02-2023? Or ultimatly accept all dat formats?

2 more prefered additions:

  1. Option to reset the filter
  2. Can I search for multiple values?

If you want to search by date, date_hierarchy is a good option.

Thank you Rigo. I look nice when added. But I would prefer if my search field would just accept 12-02-2023 as well. Now it only accepts 2023-02-12
Maybe I will adde Date_hyarchie later.

This is my code now:

    def get_search_results(self, request, queryset, search_term):
        queryset, use_distinct = super().get_search_results(request, queryset, search_term)
        if search_term:
            search_fields = self.get_search_fields(request)
            search_queries = Q()
            for term in search_term.split():
                if '-' in term:
                    try:
                        day, month, year = term.split('-')
                        # Handling both date formats: '12-02-2023' and '2023-02-12'
                        search_date = datetime.strptime(term, '%d-%m-%Y').strftime('%Y-%m-%d')
                        search_queries |= Q(start_date__icontains=search_date)
                    except ValueError:
                        pass
                else:
                    for field in search_fields:
                        search_queries |= Q(**{f'{field}__icontains': term})
            queryset = queryset.filter(search_queries)
        return queryset, use_distinct

But still does not accept 12-02-2023

In think there are two thing to improve:

  1. You should make a Try-Except for each date format.
  2. In this line:
 search_date = datetime.strptime(term, '%d-%m-%Y').strftime('%Y-%m-%d')

you are using the variable “term”, but this variables hasn’t change, so it would be better:

 search_date = datetime.strptime(f"{day}{month}{year}", "%d%m%Y").date()

Don´t forget remove the dashes, because the final F-strings doesn’t contain any dash.

Hi Rigo,

This is my code now. Still only accepting 2023-02-12

    def get_search_results(self, request, queryset, search_term):
        queryset, use_distinct = super().get_search_results(request, queryset, search_term)
        if search_term:
            search_fields = self.get_search_fields(request)
            search_queries = Q()
            for term in search_term.split():
                if '-' in term:
                    try:
                        day, month, year = term.split('-')
                        # Handling both date formats: '12-02-2023' and '2023-02-12'
                        search_date = None
                        try:
                            search_date = datetime.strptime(f"{year}-{month}-{day}", "%Y-%m-%d").date()
                        except ValueError:
                            pass
                        if not search_date:
                            try:
                                search_date = datetime.strptime(f"{day}-{month}-{year}", "%d-%m-%Y").date()
                            except ValueError:
                                pass
                        if search_date:
                            search_queries |= Q(start_date__icontains=search_date)
                    except ValueError:
                        pass
                else:
                    for field in search_fields:
                        search_queries |= Q(**{f'{field}__icontains': term})
            queryset = queryset.filter(search_queries)
        return queryset, use_distinct

What happens when you input 12-02-2023? What happens when you input 2023-02-12?

I think you should add some prints in some lines of your code in order to debug and see whats happening. I also think that you should use Regex in order to determinate if a date in both formats has been input.

I don’t understand why do you use:

search_queries = Q()
search_queries |= Q(start_date__icontains=search_date)

Hi Rigo,

This is a screenshot of my ShiftAdmin page. I want the search option to look in any of the shift values. EG look for a status, look for a Site etc. And look for a specific start_date. All other searches work fine. Only the start_date needs 2023-02-12 in order to give a result. When I input 12-02-2023 (european format) it gives no result.

ShiftAdmin is based on the Shift model. The portion that takes care of the search I posted in my previous post. I must confes that I use ChatGPT to help me get code right. But that does not solve all my problems as you can see,

I see the problem, ChatGPT it helps, but you need to understand your code.

As I wrote before, I think you should use Regex in order to match the type of date the search will consume, and you have to write the correct Queryset in order to filter the results.

Lazy as ever :wink: Yes I need more understanding of the python code. I will look at regex and find out how this might help. For now I put the date issue on the TODO list and just enter the USA format 2023-02-12