0

I need to annotate each query in queryset using a model method:

class myModel(models.Model):
    ...

    def myModel_foo(self):
        ....
        return myModel_foo

I need something like .annotate(myModel_foo=myModel.myModel_foo()). The problem is myModel_foo() requires self. I tried iterating over queryset and using query.annotate(myModel_foo=myModel.myModel_foo(self)), but i got object has no attribute 'annotate' error. What's the correct approach?

UPDATE

OK, the idea is this: i have two models with single to one relation.

class myModel1(models.Model):
  fk = ForeignKey(myModel2)
  status = ChoiceField

class myModel2(models.Model):

  def get_status(self):
    # query all objects from myModel1, get status of the last one and 
    # return it
    return get_status

Then I want to send a queryset with status included in it via ajax call.

qs = MyModel2.objects.all()
qs_json = serializers.serialize('json', qs)
        return HttpResponse(qs_json, content_type='application/json')

How can i access it in template then in a way like qs_json[0].get_status?

3
  • You can not annotate with a function call, unless you call the function, and the result is an expression like Sum('field') for example. Commented Jun 3, 2020 at 20:27
  • Perhaps it is more helpful if you define a concrete example. Commented Jun 3, 2020 at 20:34
  • I described it in main post update Commented Jun 4, 2020 at 11:28

1 Answer 1

1

Just add a property to the model and don't use the "annotation" at all. like:

class MyModel(models.Model):
    @property
    def foo(self):
        ....
        return self.bar()

But be careful with N+1 queries problem if the bar makes extra queries. You can describe your particular case and I will help you with this.

UPDATE:

There still unclear is there extra queries or not. If not, you can still use the property. You just need the right serializer like this:

from rest_framework import serializers


class MyModelSerializer(serializers.ModelSerializer):
    foo = serializers.CharField(read_only=True)

    class Meta:
        model = MyModel
        fields = [
            # other fields
            'foo'
        ]

return Response(MyModelSerializer(MyModel.objects.all(), many=True).data)
Sign up to request clarification or add additional context in comments.

1 Comment

I described it in main post

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.