Django admin list view show external url data in custom column

Viewed 1093

we have a list view something like below enter image description here

Now lets say we want to add one more column in the view which doesn't exist in model. so we can do that by creating a method inside admin class.

class PageAdmin(admin.ModelAdmin):

    list_display = ["id", "title", "slug", "author", 'updated', 'custom_field']

    def custom_field(self, obj):
        # logic...
        return True # or False based on above logic

This is simple. Now lets take a more complicated scenario where I need this column to be populated based on the result of goodreads.com search. I mean I'll search objects title on goodreads and find the exact title if found then will return True else False.

For e.g there is a page object and title of this is hunger games so when I search this, I'll get https://www.goodreads.com/search?query=hunger+games

I'll parse the result and check if exact title exist in top 10 results.

class PageAdmin(admin.ModelAdmin):

    list_display = ["id", "title", "slug", "author", 'updated', 'custom_field']

    def custom_field(self, obj):
        # search on goodreads.com, parse results and match with obj.title
        return True # or False based on above logic

The problem with this approach is that it makes admin page very slow.. since it will get data for all objects in a page(normally 100 objects)

How can I improve this? is there any asynchronous way to do this without changing much html/css/js. how can I use changelist_view method in admin class for my use case

PS: I would also like to consider bulk search approach in case if it is a different domain. I mean instead of hitting search api 100 times, I'll hit only once and pass all object's title(comma separated). https://api.goodreads.com/search?query=title1,title2,title3...

assuming this will return only exact matching books and based on id I can show True or False on admin page

PPS: I can't add another column in db table, if external service is down or taking too long to respond, I'll show some relevant message.

1 Answers
class OrderAdmin(admin.ModelAdmin):

    list_display = ["id", "title", "slug", "author", 'updated', 'custom_field']

    def custom_field(self, obj):
        return obj.title in self.found_in_goodreads

    def get_paginator(self, *args, **kwargs):
        paginator = super().get_paginator(*args, **kwargs)
        request, queryset, count = args
        page = int(request.GET.get('p', 1))  #  For current page only
        titles = paginator.page(page).object_list.values_list('title', flat=True)

        # search_goodreads
        # url = "https://api.goodreads.com/search?query={}".format(''.join(titles))
        # response = requests.get(url)
        # parse the response and store titles in the list
        # self.found_in_goodreads = [title for titles in response]
        return paginator

Additionally, you must handle cases when goodreads server is down, returning 400, timeout etc.

Related