Включение дочерних ресурсов в API Django Tastypie

Я планирую сайт с Django и Tastypie для REST API, и мне сложно найти «правильный» способ включения дочерних ресурсов в возвращаемый ресурс.

В качестве песочницы я сделал небольшое приложение с моделью Ticket и моделью TicketComment, где комментарии относятся к заявке. Я просмотрел рецепт кулинарной книги Tastypie на вложенных ресурсах (http://django-tastypie.readthedocs.org/en/latest/cookbook.html#nested-resources), но мне трудно понять, почему я должен это делать. . В приведенном ниже коде используется django.forms.models.model_to_dict() для добавления комментариев в тикет, но я думаю, что где-то здесь должна быть «ошибка».

Есть ли причина, по которой я не должен делать то, что делаю сейчас? Кроме того, есть ли для этого более чистый образец, чем тот, что указан в поваренной книге?

Модели следующие:

# tickets/models.py

from django.db import models

class Ticket(models.Model):
    title = models.CharField(max_length=200)
    create_ts = models.DateTimeField(auto_now_add=True)
    submitter_email = models.EmailField()
    PRIORITY_CHOICES = (
        ('H', 'High'),
        ('M', 'Medium'),
        ('L', 'Low'),)
    priority = models.CharField(max_length=1, choices=PRIORITY_CHOICES)
    description = models.TextField()
    STATUS_CHOICES = (
        ('NEW', 'New & Unclaimed'),
        ('WIP', 'Work In Progress'),
        ('RES', 'Resolved'),
        ('CLS', 'Closed'),)
    status = models.CharField(max_length=3, choices=STATUS_CHOICES)

    def __unicode__(self):
        return "<Ticket:%d:%s>" % (self.id, self.title,)

class TicketComment(models.Model):
    ticket = models.ForeignKey(Ticket)
    comment_ts = models.DateTimeField(auto_now_add=True)
    commenter_email = models.EmailField()
    comment = models.TextField()

    def __unicode__(self):
        return "<TicketComment:%d:%d>" % (self.ticket.id, self.id,)

Ресурсы следующие:

# tickets/api.py

from tastypie import fields
from tastypie.resources import ModelResource
from tickets.models import Ticket, TicketComment
from django.forms.models import model_to_dict

class TicketResource(ModelResource):

    class Meta:
        queryset = Ticket.objects.all()
        resource_name = 'ticket'

    def dehydrate(self, bundle):
        comments = TicketComment.objects.filter(ticket=bundle.data['id'])
        bundle.data['comments'] = [model_to_dict(c) for c in comments]
        return bundle

class TicketCommentResource(ModelResource):
    ticket = fields.ForeignKey(TicketResource, 'ticket')

    class Meta:
        queryset = TicketComment.objects.all()
        resource_name = 'comment'

Вывод выглядит следующим образом:

{
   comments: [
        {
            comment: "This is the first comment.",
            commenter_email: "[email protected]",
            id: 1,
            ticket: 1
        },
        {
            comment: "This is the second comment.",
            commenter_email: "[email protected]",
            id: 2,
            ticket: 1
        }
    ],
    create_ts: "2011-10-17T15:55:11.372000",
    description: "This is the first ticket.",
    id: "1",
    priority: "M",
    resource_uri: "/api/v1/ticket/1/",
    status: "NEW",
    submitter_email: "[email protected]",
    title: "First Ticket"
}

person Doug    schedule 19.10.2011    source источник


Ответы (2)


Вы ищете связанные поля: http://django-tastypie.readthedocs.org/en/latest/fields.html#relationship-fields

person Issac Kelly    schedule 19.10.2011
comment
Спасибо, это имеет гораздо больше смысла, однако все, что я получаю, это URL-адрес дочерних комментариев. Если вместо этого мне нужны сериализованные ресурсы, есть ли простой способ их получить? - person Doug; 19.10.2011
comment
используйте аргумент full=True в своем объявлении - person Issac Kelly; 19.10.2011
comment
Идеально, именно то, что я хотел. Спасибо! - person Doug; 19.10.2011

Можете ли вы опубликовать свое решение?

У меня тот же вариант/модели использования (отношение внешнего ключа, установленное в «дочерней таблице», указывающее обратно на родительскую таблицу), но я не могу его разрешить.

Решение, которое я видел, состоит в том, чтобы добавить эту строку в ваш TicketResource на уровне класса НЕ внутри метаподкласса:

comments = fields.ToManyField('TicketCommentResource', 'ticket', full=True)

Затем, возможно, также добавьте это в TicketCommentResource, опять же на уровне класса:

event = fields.ForeignKey('TicketResource', 'event')

Но я всегда получаю сообщение об ошибке, что ресурс моего родительского объекта (в вашем примере TicketResource) не имеет атрибута «билет», который является вторым термином, отправленным в ToManyField.

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

Спасибо!

person Jason Leidigh    schedule 17.01.2013
comment
Хотел добавить это как комментарий, но не было возможности. - person Jason Leidigh; 18.01.2013