Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why won't serialize capture annotate fields?

I had no idea adding data to a queryset would be so hard. It's like, if it didn't come directly from the db then it might as well not exist. Even when I annotate, the new fields are 2nd class citizens and aren't always available.

Why won't serialize capture my annotate fields?

Model

class Parc(models.Model):
    # Regular Django fields corresponding to the attributes in the
    # world borders shapefile.
    prop_id = models.IntegerField(unique=True)  # OBJECTID: Integer (10.0)
    shp_id = models.IntegerField()

    # GeoDjango-specific: a geometry field (MultiPolygonField)
    mpoly = models.MultiPolygonField(srid=2277)
    sale_price = models.DecimalField(max_digits=8, decimal_places=2, null=True)
    floorplan_area = models.DecimalField(max_digits=8, decimal_places=2, null=True)
    price_per_area = models.DecimalField(max_digits=8, decimal_places=2, null=True)
    nbhd = models.CharField(max_length=200, null=True)
    # Returns the string representation of the model.
    def __str__(self):              # __unicode__ on Python 2
        return str(self.shp_id)

Query:

parcels = Parc.objects\
    .filter(prop_id__in=attrList)\
    .order_by('prop_id') \
    .annotate(avg_price=Avg('sale_price'),
              perc_90_price=RawAnnotation('percentile_disc(%s) WITHIN GROUP (ORDER BY sale_price)', (0.9,)),
              )
geojson = serialize('geojson', parcels)  

When I print geojson it has no key/values for avg_price or perc_90_price. At this point, I'm leaning towards creating a dummy field and then populating it with the my customer calculations after I retrieve the queryset but I'm open to ideas.

Helper class

class RawAnnotation(RawSQL):
"""
RawSQL also aggregates the SQL to the `group by` clause which defeats the purpose of adding it to an Annotation.
"""
def get_group_by_cols(self):
    return []
like image 507
Openmic Avatar asked Sep 08 '17 17:09

Openmic


1 Answers

I use annotations with Django Rest Framework and the Serializers in that library.

In particular, the serializer method allows you to access the query set. You can do something like this.

class SomeSerializer(serializers.ModelSerializer):
  avg_price = serializers.SerializerMethodField()

  def get_avg_price(self, obj):
    try:
        return obj.avg_price
    except:
        return None

http://www.django-rest-framework.org/api-guide/fields/#serializermethodfield

like image 133
sww314 Avatar answered Oct 18 '22 09:10

sww314