Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Django admin filter list with custom model manager extra methods

I have an Address model that contains two float fields, lat and lng. I have written a custom model manager with a nearby(lat, lng, distance) method that uses raw SQL to return only Addresses which lie within a certain radius. (GeoDjango appeared to be overkill).

Example call: Address.objects.nearby(53.3, 13.4, 10) (returns QuerySet)

Now I want to dynamically filter Address objects in the Django admin using this method (ideally letting the user pick a location on a Google map and a max distance using a slider). I have no idea how to achieve that. Can anyone point me in the right direction?

CLARIFICATION You don't need to write any JavaScript for me, I just want to know how to make Django admin evaluate extra Query parameters in the URL, such that I can do queries like /admin/appname/address/?lat=53&long=13&dist=10. I can then probably figure out how to stuff a Google map and the required JavaScript magic into the template myself.

UPDATE I've tried to overwrite queryset in the ModelAdmin like so:

def queryset(self, request):
    try:
        lat = float(request.REQUEST['lat'])
        lng = float(request.REQUEST['lng'])
        dist  = int(request.REQUEST['dist'])
        matches = Address.objects.nearby(lat=lat, lng=lng, dist=dist)
        return matches
    except:
        return super(ReportAdmin, self).queryset(request)

However, the admin does not like it and returns with ?e=1, without filtering the results.

like image 402
nisc Avatar asked Sep 15 '26 07:09

nisc


1 Answers

I've added this to the ModelAdmin of the object class that has the address as a FK:

def lookup_allowed(self, lookup, *args, **kwargs):
    if lookup == 'address__dst':
        return True
    return super(ReportAdmin, self).lookup_allowed(lookup, args, **kwargs)

I've added this to the model

def _filter_or_exclude(self, negate, *args, **kwargs):
    try:
        value = kwargs.pop('address__dst')
        matches = self.nearby(*map(float, value.split(',')))
        pks = [m.pk for m in matches]
        kwargs.update({ 'pk__in': pks })
    except:
        pass
    return super(ReportQuerySet, self)._filter_or_exclude(negate, *args, **kwargs)

allowing me to filter like ?address_dst=lat,lng,dst.

Is there a nicer solution?

like image 109
nisc Avatar answered Sep 16 '26 19:09

nisc



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!