liberation / django-elasticsearch

Simple wrapper around elasticsearch-py to index/search a django Model.
MIT License
212 stars 73 forks source link

Serializer on ManyToMany value #65

Closed yarnball closed 7 years ago

yarnball commented 7 years ago

Hi,

Nice work on this repo.

I am trying to implement a function to modify my data called get_grouped_tags.

However, I keep getting an error 'QuerySet' object has no attribute 'tag'.

How do I handle M2M's on your serializer? Thanks

myapp/models.py

class Tag(models.Model):
    name = models.CharField("Name", max_length=5000, blank=True)
    taglevel = models.IntegerField("Tag level", null=True, blank=True)

class Item(EsIndexable, models.Model):
    title = models.CharField("Title", max_length=10000, blank=True)
    tag = models.ManyToManyField('Tag', blank=True)
    deleted = models.BooleanField(default=False)

    # def get_grouped_tags(self):
    #     tag = self.tag.order_by('taglevel')
    #     grouped_tags = {
    #         tag_level: [
    #             { 'name': tag_of_level.name, 'taglevel': tag_of_level.taglevel, }
    #             for tag_of_level in tags_of_level
    #         ] for tag_level, tags_of_level
    #         in groupby(tag, lambda tag: tag.taglevel)
    #     }
    #     return grouped_tags

    class Elasticsearch(EsIndexable.Elasticsearch):
        serializer_class = MyModelEsSerializer
        fields = ['title', 'tag']

myapp/elastic/serializers.py

class MyModelEsSerializer(EsJsonSerializer):
    def serialize_tag(self, instance, field_name):
        tag = getattr(instance.tag.order_by('taglevel'), 'tag')
        grouped_tags = {
            tag_level: [
                { 'name': tag_of_level.name, 'taglevel': tag_of_level.taglevel, }
                for tag_of_level in tags_of_level
            ] for tag_level, tags_of_level
            in groupby(tag, lambda tag: tag.taglevel)
        }
        return  grouped_tags
yarnball commented 7 years ago

Got it- fixed by doing

tag = instance.tag.all()

So my full result:

class MyModelEsSerializer(EsJsonSerializer):
    def serialize_tag(self, instance, field_name):
        tag = instance.tag.all()
        grouped_tags = {
            tag_level: [
                { 'name': tag_of_level.name, 'taglevel': tag_of_level.taglevel, }
                for tag_of_level in tags_of_level
            ] for tag_level, tags_of_level
            in groupby(tag, lambda tag: tag.taglevel)
        }
        return grouped_tags