Как передать модель django-simple-history в Graphene-Django?

Я создал экземпляр simple_history.models.HistoricalRecords в моей модели Notification

models.py

class Notification(models.Model):
    title = models.CharField(max_length=500)
    content = RichTextField()
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)
    history = HistoricalRecords()


class Attachment(models.Model):
    title = models.CharField(max_length=500)
    attachement = models.FileField(upload_to = user_directory_path)
    notifiaction = models.ForeignKey(Notification, on_delete=models.SET_NULL, null= True)
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)

schema.py

class AttachmentNode(DjangoObjectType):
    class Meta:
        model = Attachment
        filter_fields = ['title']
        interfaces = (relay.Node, )


class NotificationNode(DjangoObjectType):
    class Meta:
        model = Notification
        filter_fields = {
            'id': ['exact'],
            'title': ['exact', 'icontains', 'istartswith'],
        }
        interfaces = (relay.Node, )



class Query(graphene.ObjectType):
    notifications = relay.Node.Field(NotificationNode)
    all_notifications = DjangoFilterConnectionField(NotificationNode)

Это работает нормально, но я хочу, чтобы все записи также были в конечной точке graphql для HistoricalRecords(). Как я могу это сделать?

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

Получение списка изменений из списка ревизий

Похоже, что есть проблема, которую вам придется решить в первую очередь - django-simple-history хранит ревизии объектов, а не различия. Вам придется придумать, как преобразовать это

[
    <HistoricalNotification: Notification object as of 2010-10-25 18:04:13.814128>,
    <HistoricalNotification: Notification object as of 2010-10-25 18:03:29.855689>,
]

к чему-то подобному, сравнивая соседние ревизии и находя различия:

[
    "Created by Jack Pear 10 minutes ago",
    "title changed by Jack Pear 8 minutes ago",
]

В действительности вам, вероятно, нужны dicts вместо stings, так что это легче обрабатывать на frontend.

Для этого существует инструмент , включенный в django-simple-history. Вот некоторый псевдокод того, как вы можете это сделать:

class Notification(models.Model):
    title = models.CharField(max_length=500)
    content = RichTextField()
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)
    history = HistoricalRecords()

    def get_changelist(self):
        record = self.history.first()
        while record.next_record:
            delta = record.diff_against(record.next_record)
            for change in delta.changes:
                yield {
                    "field": change.field,
                    "old": change.old,
                    "new": change.new,
                    "changed_by": record.next_record.history_user,
                    "changed_at": record.next_record.history_date,
                }
            record = record.next_record

Добавление списка изменений в graphql

Нам придется объявить отдельный ObjectType для объектов списка изменений:

class ChangeListItemNode(graphene.ObjectType):
    field = graphene.ID()
    old = graphene.ID()
    new = graphene.ID()
    changed_by = graphene.Field(UserNode)
    changed_at = graphene.DateTime()

После этого мы объявляем пользовательское поле с резольвером на NotificationNode:

class NotificationNode(DjangoObjectType):
    changelist = graphene.List(ChangeListItemNode)

    class Meta:
        model = Notification
        filter_fields = {
            'id': ['exact'],
            'title': ['exact', 'icontains', 'istartswith'],
        }
        interfaces = (relay.Node, )

    @staticmethod
    def resolve_changelist(notification, info, **kwargs):
        return notification.get_changelist()

Помните, что это не тестировалось, это просто псевдокод и определенно содержит ошибки. Однако это должно послужить отправной точкой.

Вернуться на верх