Django-tastypie: حقول مختلفة لإجراءات SHOW و INDEX

تم إنشاؤها على ٢٥ أكتوبر ٢٠١٠  ·  40تعليقات  ·  مصدر: django-tastypie/django-tastypie

مرحبًا بالجميع ، هل من الممكن عرض حقول مختلفة للمورد اعتمادًا على الإجراء.

السبب الذي أريده هو تجنب إثقال إجراء الفهرس بجميع حقول has_many التي يتضمنها هذا المورد.

على سبيل المثال ، في عرض فهرس المؤلف ، أود إرجاع اسمه فقط ، ولكن بالنسبة إلى إجراء العرض ، أود تضمين جميع موارد الكتب.

شكرا،
بويان

documentation feature

التعليق الأكثر فائدة

الحل البسيط الذي أستخدمه هو تجاوز الطرق get_detail & get_list لتحرير مثل هذه الحقول.
يؤدي هذا إلى حفظ الحمل الفعلي لجلب البيانات للحقل ثم حذفها من الحزمة ، لكنني لست متأكدًا مما إذا كانت هذه الطريقة آمنة ، حيث يبدو أن كائنات المصدر لم يتم إنشاؤها في كل استدعاء لواجهة برمجة التطبيقات.
سيكون من الرائع أن يعلق أحد على هذا.

ها هو الكود:

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_exclude_fields = ['some_m2m_field']

سيسمح لنا هذا بحفظ بعض استعلام db.

  1. تمرير معلمة "طريقة" إضافية للجفاف. سيسمح هذا بتخصيص الحزمة مثل تخطي بعض الحقول غير المطلوبة في الفهرس ونريد توفير بعض النطاق الترددي.

لم أقم بتقييم 1. سيكون له تأثير على التخزين المؤقت.
ماذا تعتقد؟

خدع أيضًا في رقم 48 ، لكن لكل قضية جوانب جديرة بالاهتمام.

كنت أرغب في دفع هذه الميزة إذا كان بإمكاني ، لكنني تفوقت كثيرًا. يجب أن يكون هناك لدعم أفضل للملفات على أي حال ، لذلك يجب معالجته. سيستهدف 1.0 على هذا.

بعد فحص حالة الاستخدام الخاصة بي لهذا الأمر أكثر من ذلك بقليل ، أود أن أقترح تطبيقه كشيء أكثر مرونة من مجرد عرض / عرض قائمة. ما أحتاجه حقًا لأكون قادرًا على فعله هو أخذ علامة سلسلة استعلام مثل هذا:

& شكل = [كامل | بسيط | بلا]

وجعل المخرجات تعكس مستوى التفاصيل الذي حدده المستخدم. لقد بحثت عن طريقة لاختراق هذا ، ولكن نظرًا لتضمين / استبعاد الحقول عند إنشاء فئة 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 ، لكنه يعرض بالتفصيل ، دون الحاجة إلى الوصول إلى المورد نفسه ، يجب أن يكون الحصول على عنوان 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

سأصعد أيضًا على متن القطار ، وسيكون من الجيد الحصول على تدريب ، لكن ما أشار إليه لإدراكي . لقد قمت بتعديله قليلاً ليكون أكثر ديناميكية.

    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 ، باستخدام الإصلاح من dericcrago الآن.

+1

+1

التنفيذ الجزئي في رقم 526 ، لست متأكدًا من أنني بعت على كل ذلك وأنه يفتقر إلى الاختبارات / المستندات.

شاهدت للتو هذه التذكرة ... وأيضًا مثل طريقة "الشكل" التي ذكرها أونيكس فيش أعلاه ...

كنت أفكر في أن الحل الخاص بي في رقم 526 كان محدودًا بعض الشيء ، في حال أراد الناس "أشكالًا" مختلفة في حالات أخرى ...

إلى الاقتراحات لإزالة الحقول بعد التجفيف ... السبب الكامل لي هو تجنب حساب القيم في المقام الأول.

ومع ذلك ، فإن فكرة ربط التفاصيل ديهيدراتي للسماح بإضافة المزيد من التفاصيل بشكل مشروط ، أحب ذلك.

يبدو أن هناك تطبيقتان محتملتان ، بما في ذلك الاختبارات والمستندات. لقد كتبت واحدة في رقم 569 ورقم 538 تؤدي أيضًا وظائف مماثلة (# 538 تسمح بمرونة أكبر قليلاً نظرًا لأن use_in قد يكون قابلاً للاستدعاء). يضيف التنفيذ الخاص بي سمات meta للتحكم في هذه الوظيفة (والتي تتوافق مع السمة الحالية fields ) بينما يضيف # 538 سمة للحقول. كلاهما يبدو صالحًا ، مجرد قرار تصميم يتعلق بالطريقة التي يجب أن تسلكها. تبدو الإضافة إلى meta متسقة بالنسبة لي وأسهل في الاستخدام نظرًا لأنه يمكن إنشاء بعض الحقول تلقائيًا وقد لا يكون تعديل معلمات التهيئة الخاصة بها ممكنًا. قد يكون البديل الآخر هو الجمع بين طلبات السحب والسماح بتعيين المعلمة use_in تلقائيًا استنادًا إلى السمة meta ، ولكن يبدو أن هذا يضيف تعقيدًا إلى واجهة برمجة التطبيقات أكثر مما هو ضروري. شكرًا لـ issackelly للإشارة إلي طلبات السحب ذات الصلة.

[رنين لأنني كنت السبب الأصلي وراء # 538 ، إنه تنظيف لـ # 526]
له معنى كبير ... فإن نهج Meta ، في الواقع ، سوف يتناغم مع قائمة المستبعدين لـ ModelResource ، إلخ ...

كما قلت في بطاقة أخرى ، فإن الحل "البسيط" مثل هذا سيكون ، IMHO ، كافيًا لإصدار 1.0 ... مع حل أكثر تعقيدًا مثل "الأشكال" التي يمكن تحديدها من قِبل العميل والتي ربما تكون مرغوبة لإصدار لاحق .. .

موافقfunkybob ، بالتأكيد سيكون الحل الأكثر تعقيدًا مفيدًا من جانب العميل ، ولكن سيكون من الجيد تضمين هذه الوظيفة في أسرع وقت ممكن حتى يمكن البدء في استخدامها قبل إصدار 1.0.

باستخدام PR في تطبيق الإنتاج ، أحب حقًا مرونة رد الاتصال التي يوفرها # 538. لدي حالتان من حالات الاستخدام حيث يتعين علي إخفاء مورد في وقت التشغيل بناءً على الإذن.

لن يكون هذا ممكنًا بالنسبة لي باستخدام # 569

مرحبا اي اخبار أن العلاقات العامة تجعل الحياة أسهل ، شكرًا!

الذهاب مع الاختراق المقدم منdericcrago

+1

الحل البسيط الذي أستخدمه هو تجاوز الطرق get_detail & get_list لتحرير مثل هذه الحقول.
يؤدي هذا إلى حفظ الحمل الفعلي لجلب البيانات للحقل ثم حذفها من الحزمة ، لكنني لست متأكدًا مما إذا كانت هذه الطريقة آمنة ، حيث يبدو أن كائنات المصدر لم يتم إنشاؤها في كل استدعاء لواجهة برمجة التطبيقات.
سيكون من الرائع أن يعلق أحد على هذا.

ها هو الكود:

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 لحل dnozay

+1 @ dnozay ، رائع

لاحظ أنه إذا كنت تريد أن يعمل get_resource_uri بشكل صحيح مع عرض تفاصيل المستخدم ، فستحتاج إلى إضافة ما يلي بعد تحديد UserResource .

UserResourceDetail.get_resource_uri = UserResource().get_resource_uri

وإلا فسيكون resource_uri فارغًا في كافة الاستجابات التفصيلية.

يحتمل أن تكون ذات صلة: # 1265

هل كانت هذه الصفحة مفيدة؟
0 / 5 - 0 التقييمات