Django-tastypie: Различные поля для действий ПОКАЗАТЬ и ИНДЕКС

Созданный на 25 окт. 2010  ·  40Комментарии  ·  Источник: django-tastypie/django-tastypie

Привет всем, можно ли отображать разные поля для ресурса в зависимости от действия.

Причина, по которой я хочу это, - избежать обременения действия индекса всеми полями has_many, которые включает ресурс.

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

Благодарность,
Боян

documentation feature

Самый полезный комментарий

Я использую простой обходной путь - переопределить методы get_detail & get_list для редактирования таких полей.
Это экономит накладные расходы на фактическую выборку данных для поля и последующее их удаление из пакета, но я не уверен, является ли этот метод потокобезопасным, поскольку похоже, что объекты Resource не создаются при каждом вызове api.
Было бы здорово, если бы кто-нибудь мог это прокомментировать.

Вот код:

class ArticleResource(BaseModelResource):
    owner = fields.ToOneField(UserResource, 'owner', full=True)

    class Meta:
        resource_name = "articles"

    def get_list(self, request, **kwargs):
        self.fields.pop("comments", None)
        return super(ArticleResource, self).get_list(request, **kwargs)

    def get_detail(self, request, **kwargs):
        self.fields["comments"] = fields.ToManyField(CommentResource, 'comments', full=True)
        return super(ArticleResource, self).get_detail(request, **kwargs)

Все 40 Комментарий

+1
Я очень надеюсь на эту функцию: «поле сведений» и «поле списка» можно разделить

+1 (через дубликат в # 44)

Мне кажется, что есть две вещи, которые могут упростить получение подмножества данных в действиях индекса:

  1. Заставьте full_dehydrate использовать разные поля для методов index и get. Может быть что-то вроде:

Мета:
index_exclude_fields = ['some_m2m_field']

Это позволит нам сэкономить некоторые запросы к базе данных.

  1. Передайте дополнительный параметр «метод» для обезвоживания. Это позволит настроить пакет, например, пропустить некоторые поля, которые не нужны в индексе, и мы хотим сэкономить некоторую пропускную способность.

Я не оценил 1. повлияет на кеширование.
Что вы думаете?

Тоже обманут в №48, но у каждой проблемы есть свои аспекты.

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

Изучив мой вариант использования для этого еще немного, я хотел бы предложить его реализовать как нечто более гибкое, чем просто отображение / список представлений. Что мне действительно нужно сделать, так это взять такой флаг строки запроса:

& shape = [полный | простой | нет]

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

+1

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

Если будет разработан механизм для отображения различных полей, было бы полезно, если бы он также мог быть интегрирован с аутентификацией. Возможность отображать больше / меньше полей зависит от разрешений пользователя, что было бы очень мощно. Если это уже возможно, мне не удалось найти упоминания об этом.

+1

+1

+1

+1

+1

+1

+1

Я бы ожидал, что смогу управлять отображаемыми полями (используя поля или исключающие) для каждого метода (POST, PUT, GET) в дополнение к списку / детали.

Вот обходной путь, см. Пример ниже: вы ничего не исключаете из модели ресурсов исходной модели (UserResource в примере), поэтому она будет заполнена в представлении индекса. Вам нужно перейти к методу обезвоживания ресурса модели, который включает вашу подмодель (BlogPostResource включает в себя автора) и просто удалить элементы пакета.

пример:

class BlogPostResource(ModelResource):
     author = fields.ForeignKey(UserResource, 'author', full=True)
     ....
     class Meta:
         ...

def dehydrate(self, bundle):
         del bundle.data['author'].data['field_you_dont_wanna_show_here']
         del bundle.data['author'].data['field_you_dont_wanna_show_here']
         return bundle

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

Что вы думаете?

Пример очень, очень грязного обходного пути: не показывает поля проекта в list_view, но он делает в detail_view, без необходимости доступа к самому ресурсу, получение самого URL-адреса без жесткого кодирования должно быть возможно, но у него не было времени проверить его :

class CompanyResource(ModelResource):
       """
       Tastypie resource for Company
      """
       projects = fields.ToManyField('api.resources.ProjectResource',
                                  'projects',full=True)
       class Meta:
           queryset = Company.objects.all()
           resource_name = 'companies'

       def dehydrate(self, bundle):
           if bundle.request.path == "/api/v1/companies/":
               del bundle.data['projects']
           return bundle

+1

+1

+1

Я также сяду на борт, было бы неплохо иметь поезд, но того, что указал @ashwoods , достаточно, чтобы меня

    def dehydrate(self, bundle):
        if self.get_resource_uri(bundle) == bundle.request.path:
            print "Detail"

        if self.get_resource_uri(bundle) != bundle.request.path:
            print "Not Detail - Could be list or reverse relationship."

        return bundle

Я подумал об этом еще раз и придумал что-то, что позволяет мне делать то, что, как мне кажется, искал @bmihelac .

Используя предоставленный пример @ashwoods , предположим, что мы хотим отобразить поле проектов только в том случае, если это был подробный ответ:

class CompanyResource(ModelResource):
    """
    Tastypie resource for Company
    """

    class Meta:
        queryset = Company.objects.all()
        resource_name = 'companies'
        additional_detail_fields = {'projects': fields.ToManyField('api.resources.ProjectResource', 'projects',full=True)}

    def dehydrate(self, bundle):
        # detect if detail
        if self.get_resource_uri(bundle) == bundle.request.path:
            # detail detected, include additional fields
            bundle = self.detail_dehydrate(bundle)

        return bundle

    # detail_dehydrate is basically full_dehydrate
    # except we'll loop over the additional_detail_fields
    # and we won't want to do the dehydrate(bundle) at the end
    def detail_dehydrate(self, bundle):
        """
        Given a bundle with an object instance, extract the information from it
        to populate the resource.
        """
        # Dehydrate each field.
        # loop over additional_detail_fields instead
        #for field_name, field_object in self.fields.items():
        for field_name, field_object in self._meta.additional_detail_fields.items():
            # A touch leaky but it makes URI resolution work.
            if getattr(field_object, 'dehydrated_type', None) == 'related':
                field_object.api_name = self._meta.api_name
                field_object.resource_name = self._meta.resource_name

            bundle.data[field_name] = field_object.dehydrate(bundle)

            # Check for an optional method to do further dehydration.
            method = getattr(self, "dehydrate_%s" % field_name, None)

            if method:
                bundle.data[field_name] = method(bundle)

        # dehydrating the bundle will create an infinite loop
        #bundle = self.dehydrate(bundle)
        return bundle

+1, пока использую исправление от

+1

+1

Частичная реализация в # 526, не уверен, что мне все это нравится, и в нем отсутствуют тесты / документы.

Только что видел этот билет ... а также подход "формы", упомянутый onyxfish выше ...

Я думал, что мое решение в # 526 было немного ограниченным, на случай, если люди захотят другие «формы» в других случаях ...

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

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

Похоже, что доступны две возможные реализации, включая тесты и документы. Я написал один в # 569, а # 538 также выполняет аналогичные функции (# 538 дает немного больше гибкости, поскольку use_in может быть вызываемым). Моя реализация добавляет атрибуты meta для управления этой функциональностью (что согласуется с текущим атрибутом fields ), а # 538 добавляет атрибут к полям. Оба кажутся верными, просто дизайнерское решение относительно того, в каком направлении двигаться. Добавление в мета кажется мне последовательным и более простым в использовании, учитывая, что некоторые поля могут быть автоматически сгенерированы, и изменение их параметров инициализации может быть невозможно. Другой альтернативой было бы объединить оба запроса на вытягивание и разрешить автоматическую установку параметра use_in на основе атрибута meta , однако это, похоже, добавляет больше сложности API, чем необходимо. Спасибо @issackelly за то, что он указал

[вмешивается, поскольку я был первопричиной создания № 538, это была очистка моего № 526]
Имеет большой смысл ... мета-подход действительно объединит список исключений для ModelResource и т. Д.

Как я сказал в другом билете, "простое" решение, подобное этому, было бы, IMHO, достаточным для версии 1.0 ... с более сложным решением, таким как "выбираемые клиентом" формы ", возможно, желательно для более позднего выпуска .. .

@funkybob Согласен, конечно, более сложное решение было бы полезно со стороны клиента, но было бы неплохо включить эту функцию как можно скорее, чтобы ее можно было использовать до выпуска 1.0.

На самом деле, используя PR в производственном приложении, мне очень нравится гибкость обратного вызова, обеспечиваемая # 538. У меня есть несколько случаев использования, когда мне нужно скрывать ресурс во время выполнения на основе разрешения.

Для меня это было бы невозможно, используя # 569

Привет, есть новости? Этот пиар делает жизнь проще, спасибо!

Собираюсь с хака, предоставленного @dericcrago

+1

Я использую простой обходной путь - переопределить методы get_detail & get_list для редактирования таких полей.
Это экономит накладные расходы на фактическую выборку данных для поля и последующее их удаление из пакета, но я не уверен, является ли этот метод потокобезопасным, поскольку похоже, что объекты Resource не создаются при каждом вызове api.
Было бы здорово, если бы кто-нибудь мог это прокомментировать.

Вот код:

class ArticleResource(BaseModelResource):
    owner = fields.ToOneField(UserResource, 'owner', full=True)

    class Meta:
        resource_name = "articles"

    def get_list(self, request, **kwargs):
        self.fields.pop("comments", None)
        return super(ArticleResource, self).get_list(request, **kwargs)

    def get_detail(self, request, **kwargs):
        self.fields["comments"] = fields.ToManyField(CommentResource, 'comments', full=True)
        return super(ArticleResource, self).get_detail(request, **kwargs)

+1

Другой обходной путь - использовать разные ресурсы для просмотра подробностей и списков:

from tastypie.resources import ModelResource
from django.contrib.auth.models import User

# detail will show everything except password
class UserResourceDetail(ModelResource):
    class Meta:
        queryset = User.objects.all()
    excludes = ('password',)
    resource_name = 'user'

# list will only show username & date_joined (and exclude password)
class UserResource(UserResourceDetail):
    class Meta(UserResourceDetail.Meta):
        fields = ('username', 'date_joined')
    get_detail = UserResourceDetail().get_detail

# ... register & use UserResource

+1

+1 за обходной путь

+1 @dnozay ,

Обратите внимание: если вы хотите, чтобы get_resource_uri правильно работал с подробным представлением пользователя, вам необходимо добавить следующее после определения UserResource .

UserResourceDetail.get_resource_uri = UserResource().get_resource_uri

В противном случае resource_uri будет пустым во всех подробных ответах.

Возможно связанный: # 1265

Была ли эта страница полезной?
0 / 5 - 0 рейтинги