2

This one is interesting to solve. I am building a module to register address for hospital, medical store and doctors. There is an abstracted model PrimaryAddress and a subclass called MedicalStorePrimaryAddress, and more subclasses will use the same abstracted model. I am using django rest framework to get the listings based on proximity (latitude, longitude and city). Now how could I filter it all using parent class, i.e PrimaryAddress model as I want to filter all the entities, i.e hospital, medical store and doctor nearby. I have looked into django-polymorphic library but it doesnt help with geodjango and abstract class. Any help suggestion is appreciated. Thanks Here is the code sample:

#  MODELS

class PrimaryAddress(gismodels.Model):
    street = gismodels.CharField(max_length=255)
    city = gismodels.CharField(max_length=60)
    state = gismodels.CharField(max_length=100,
                                choices=settings.US_STATES,
                                default="CT")
    landmark = gismodels.TextField()
    latitude = gismodels.FloatField(null=True, blank=True)
    longitude = gismodels.FloatField(null=True, blank=True)
    location = gismodels.PointField(null=True, blank=True)

    objects = gismodels.GeoManager()

    def __unicode__(self):
        return self.street

    class Meta:
        verbose_name = "Address"
        verbose_name_plural = "Addresses"
        abstract = True

    def save(self, *args, **kwargs):
        if self.latitude and self.longitude:
            self.location = Point(self.longitude, self.latitude)

        super(PrimaryAddress, self).save(*args, **kwargs)


class MedicalStoreAddress(PrimaryAddress):
    medical_store = gismodels.OneToOneField(MedicalStore, related_name="medical_store_address",
                                            on_delete=gismodels.CASCADE, null=True, blank=True)

    # objects = gismodels.GeoManager()

    def __unicode__(self):
        return self.street

    class Meta:
        verbose_name = "Medical Store Address"
        verbose_name_plural = "Medical Store Addresses"

    def save(self, *args, **kwargs):
        if self.latitude and self.longitude:
            self.location = Point(self.longitude, self.latitude)

        super(MedicalStoreAddress, self).save(*args, **kwargs)

# VIEW
class ProximityFilter(ListAPIView):
    serializer_class = AddressSerializer
    # authentication_classes = (authentication.TokenAuthentication, authentication.SessionAuthentication,)
    # permission_classes = (permissions.IsAuthenticated,)
    pagination_class = StandardResultsSetPagination

    def get_queryset(self):
        longitude = self.kwargs.get('longitude')
        latitude = self.kwargs.get('latitude')
        city = self.kwargs.get('city')
        current_point = GEOSGeometry('POINT(%s %s)' % (longitude, latitude), srid=4326)
        # raise
        queryset = MedicalStoreAddress.objects.filter(city__iexact=city, location__distance_lte=(current_point, D(mi=700000000))).distance(
            current_point).order_by('distance')
        return queryset

# SERIALIZER

class AddressSerializer(HyperlinkedModelSerializer):


    class Meta:
        model = DoctorPrimaryAddress
        fields = ('pk', 'street', 'latitude', 'longitude', 'city')

This paste expires on 2018-03-29 21:26:23. View raw. Remove now (Why am I seeing this?) Pasted through web.
Maverick
  • 2,738
  • 24
  • 91
  • 157
  • 2
    I could be very wrong, but I don't believe you can do anything directly on the abstract base class. You'd have to make it non-abstract, and then could query direct on PrimaryAddress, and those model objects would then have a `medicalstoreaddress` (if there is a MedicalStoreAddress linked to that PrimaryAddress) If you want to stay abstract, you'd have to query each child model class and could then union() them together, I suppose. – Shane Mar 28 '18 at 22:30
  • making it non-abstract will give me queryset of different entities but not based on proximity. Isnt it? – Maverick Mar 28 '18 at 22:37
  • 2
    You would get a set of PrimaryAddress models, yes, but you can do the same filter call you're using now, just on the PrimaryAddress model: `queryset = PrimaryAddress.objects.filter(city__iexact=city, location__distance_lte=(current_point, D(mi=700000000))).distance( current_point).order_by('distance')` Then looping through it, you can access the related child model via the `[childclassnamenospaces]` attribute, if you need access to it. – Shane Mar 28 '18 at 22:42
  • No I cant do it without making PrimaryAddress non-abstract. – Maverick Mar 28 '18 at 22:49
  • 2
    I don't know if you have any reasons to design your models as is. For me, it sounds better to have a `address` field (OneToOne or ForeignKey) attached directly to the `MedicalStore` model, pointing to the `PrimaryAddress` model. – albar Mar 29 '18 at 08:29
  • Yes you are right, that could be done. The reason why I wanted this way is because I wanted a staff status user to login to admin and enter details of entity, i.e doctor or hospital as inline. Could that still be done with one to one relationship? And should I remove abstract tag from PrimaryAddress in that case? Of course I guess as that wont create a table otherwise. – Maverick Mar 29 '18 at 08:52

0 Answers0