Возврат аннотированного набора запросов к запросам graphql на графене django

class Project(models.Model):
    name = models.CharField(max_length=189)

class Customer(models.Model):
    name = models.CharField(max_length=189)
    is_deleted = models.BooleanField(default=False)
    project = models.ForeignKey(Project, related_name="customers")

class Message(models.Model):
    message = models.TextField()
    customer = models.ForeignKey(Customer, on_delete=models.CASCADE, related_name="messages")
    created_at = models.DateTimeField(auto_now_add=True)

Я использую следующий набор запросов, чтобы получить всех клиентов в рамках определенного проекта, упорядоченных по тому, кто отправил сообщение последним.

qs = Customer.objects.filter(messages__isnull=False) \
.annotate(last_message=Max('messages__created_at')).order_by('-last_message')

Теперь я хочу использовать базовый графеновый запрос (НЕ ретранслятор), чтобы получить проект и клиентов, связанных с этим проектом, в соответствии с аннотированным набором запросов. У меня также может быть второй вариант использования, когда мне нужно будет отфильтровать набор запросов project.customers.all () в соответствии с полем в таблице клиентов (например, клиенты, у которых is_deleted = False).

В настоящее время в моей схеме graphql у меня есть

class ProjectNode(DjangoObjectType):
    class Meta:
        model = Project

class CustomerNode(DjangoObjectType):
    class Meta:
        model = Customer

class Query(graphene.ObjectType):
    project = graphene.Field(ProjectNode, id=graphene.Int(), token=graphene.String(), )
    top_chat_customers = graphene.Field(CustomerNode, project_id=graphene.Int())

     def resolve_project(self, info, **kwargs):
        pk = kwargs["id"]
        return Project.objects.filter(id=pk).first()

    def resolve_top_chat_customers(self, info, **kwargs):
        project = Project.objects.filter(id=kwargs["project_id"]).first()
        return Customer.objects.filter(project=project, messages__isnull=False) \
.annotate(last_message=Max('messages__created_at')).order_by('-last_message')

Здесь, когда я пытаюсь получить список клиентов отдельно, указав идентификатор проекта, он показывает ошибку: «Получен несовместимый экземпляр ...»

Есть идеи, как мне получить список клиентов из узла проекта и в виде отдельного запроса top_chat_customers?

Любая помощь приветствуется. Спасибо!


person Mehran    schedule 18.07.2018    source источник


Ответы (1)


Метод resolve_top_chat_customers возвращает итеративный набор запросов, а не отдельный объект Customer, поэтому в Query вам нужно указать, что вы возвращаете список:

top_chat_customers = graphene.List(CustomerNode, project_id=graphene.Int())

Кроме того, любые аннотированные поля из запроса не будут автоматически входить в схему. Если вы хотите их увидеть, вам нужно явно добавить их:

class CustomerNode(DjangoObjectType):
    last_message = graphene.String()

    class Meta:
        model = Customer

    def resolve_last_message(self, info):
        # Returns last message only if the object was annotated
        return getattr(self, 'last_message', None)
person Mark Chackerian    schedule 19.07.2018
comment
Спасибо за Ваш ответ! Я уже заметил проблему graphene.List, о которой вы упомянули, но не смог найти решения для аннотации. - person Mehran; 20.07.2018
comment
Кроме того, есть ли способ для запроса вернуть два разных объекта (например, ProjectNode и CustomerNode). Я хочу сказать, могу ли я привлечь всех клиентов в проект с аннотированным полем? - person Mehran; 20.07.2018
comment
использование prefetch_related с настраиваемой Prefetch для настройки набора запросов Customer для аннотирования сделало свое дело! Спасибо вам за помощь! - person Mehran; 20.07.2018