Включение дочерних ресурсов в API Django Tastypie - PullRequest
8 голосов
/ 19 октября 2011

Я планирую сайт с 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: "me@example.com",
            id: 1,
            ticket: 1
        },
        {
            comment: "This is the second comment.",
            commenter_email: "me@example.com",
            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: "me@example.com",
    title: "First Ticket"
}

Ответы [ 2 ]

14 голосов
/ 19 октября 2011

Вы ищете соответствующие поля: http://django -tastypie.readthedocs.org / en / latest / fields.html # relations-fields

1 голос
/ 18 января 2013

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

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

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

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

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

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

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

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

Спасибо!

...