Django-rest-framework: إضافة / التحقق من صحة العلامات الإلكترونية بسهولة.

تم إنشاؤها على ٢٩ يونيو ٢٠١١  ·  24تعليقات  ·  مصدر: encode/django-rest-framework

يمتلك Django ديكورًا رائعًا / حالة / ديكورًا معدلاً. لا يعمل مع طرق العرض المستندة إلى فئة drf ، حيث لا يمكنك تزيين "get" معهم. نظرًا لأن الحصول على إرجاع كائن ليس استجابة http ، فلا توجد طريقة لإضافة رأس etag إلى الاستجابة.

أود أن أرى طريقة للقيام بذلك من داخل drf. أفكر في شيء ما على غرار طريقة قابلة للتجاوز على مورد ، أو طريقة عرض (أو مزيج) يمكن استخدامها لإنشاء etag.

الطريقة الأخرى للقيام بذلك في django هي استخدام البرامج الوسيطة ، لكنها لا تستطيع اختصار تشغيل جسم العرض تمامًا كما يفعل المصمم.

Enhancement

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

لسوء الحظ ، فإن التنفيذ والتوثيق الافتراضي لوظيفة Etag في ملحقات drf هو ببساطة خطأ وخطير عربات التي تجرها الدواب. يغير Etag إذا تغير _request_ ، وليس إذا تغير _response_. وهو بالضبط ما تريده للتخزين المؤقت من جانب الخادم ، وهو بالضبط ما لا تريده لـ Etag.

ال 24 كومينتر

سعيد جدا لردود الفعل على هذا ، مع ذلك.

حسنًا ، في البداية ما كتبته كان هذا ....

رائع ، أجل ، أود حقًا أن أرى هذا في.

أفكار Coupla - يجب أن تكون قادرًا على استخدام View.add_header فقط ، بدلاً من طريقة العرض ._ETAG التي لديك حاليًا.
(ويبدو أنه ربما يجب نقل .add_header إلى فئة ResponseMixin.)

ثانيًا ، أود أن أرى الديكورات condition و etag و https://github.com/django/django/blob/master/django/views/decorators /http.py ، فقط استبدل زوج من add_header و ErrorResponses

لكن كان يبحث في الأشياء أكثر قليلاً ...

وربما لا تكون هذه هي الطريقة الصحيحة لمتابعة كل شيء ...

يمكنك بالفعل إرجاع HttpResponses من طرق عرض إطار عمل REST ، فهم لا يحصلون على جميع عناصر التفاوض / التسلسل المعتادة للمحتوى المطبقة. لا يقوم @last_modified و @etag و @condition إلا بإرجاع إجابات HttpRespons فارغة ، لذا فهذه ليست مشكلة حقًا.

لذا ، ما أفكر فيه هو ، إذا أضفنا ببساطة __setitem__ __getitem__ و has_header إلى فئة الاستجابة ، إذن أعتقد أن Django الحالي @last_modified ، @etag و @condition يجب أن يعمل المصممون بشكل جيد في عرض إطار عمل REST _ طالما أن العرض يستخدم النمط return Response(status, data) بدلاً من النمط return data .

سيكون من المفيد لو وثقنا ذلك ، لكن قد يكون منطقيًا أكثر من الاضطرار إلى تكرار شيء قام به Django بالفعل.

ما رأيك؟

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

قد لا يكون الأمر كذلك ، وفي هذه الحالة يبدو هذا الحل أفضل.

بعد قولي هذا ، كنت أعيد نمط بيانات الإرجاع ، حيث إنه أقل معيارية ، وعادة ما أعيد فقط الكائنات التي أريد إجراء تسلسل لها كـ json. قد نكون قادرين على جعله يعمل بكلا الطريقتين.

قد يكون هناك خيار آخر وهو mixin الذي يضيف هذه إلى فئة العرض.

ويخطر لي أيضًا أن مصممي django قد لا يفعلون الشيء الصحيح فيما يتعلق بطلبات PUT و POST و DELETE المشروطة. فقط قدمت التصحيح لسيناترا لإصلاح هذه المشكلة.

تجاهل الجزء الأخير: من الواضح أنني لم أقرأ الكود بشكل صحيح.

في الواقع ، هناك نقطة هناك: قد لا يعمل هؤلاء المصممون على أجهزة الصراف الآلي على _الطرق_ ، نظرًا لأن لديهم حجة "الذات" الإضافية. سأبحث في ذلك وأستطيع تقديم تذكرة إلى Django ، حيث يجب عليهم العمل مع CBVs أيضًا ...

آه ، حسنًا - أرى method_decorator الآن ... https://docs.djangoproject.com/en/dev/topics/class-based-views/#decorating -class-Based -views
لذلك أعتقد أن هذا لإغلاق هذا نحتاج:

  1. قليلا من التغيير والتبديل في الاستجابة
  2. بعض الوثائق الخفيفة

أنا متأكد من أنني بحثت في هذا المستند ، لكنني لم أر ذلك المصمم!

حاولت استخدام مصمم django وكانت النتيجة الأولية غريبة حقًا ، مع وجود معلومات يجب أن تنتمي فقط إلى العروض التي تظهر في وظائف etag غير ذات صلة.

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

https://bitbucket.org/vitormazzi/django-rest-framework/changeset/6f8de4500c6f

على أمل أن نبعث بعض الحياة الجديدة في هذه المشكلة الآن بعد أن أصبحنا في إصدارات 2.x.

يتم تجميع أفكاري هنا في الغالب من محاولة إضافة الوظائف في مشروع ومن قراءة هذا المنشور لذلك لا يزال قاسيًا بالتأكيد.

أرى مجالين يحتاج فيهما DRF إلى مراعاة ETags - الاستخدام في طرق العرض وكيفية الحصول على التمثيل الفريد لإصدار المثيل.

الآراء

احصل على
تحتاج طلبات GET ببساطة إلى خدمة ETag للكائنات في العنوان المناسب. يمكن أن يؤدي تغيير سطر واحد إلى RetrieveModelMixin إضافة هذا بسهولة:

def retrieve(self, request, *args, **kwargs):
    self.object = self.get_object()
    serializer = self.get_serializer(self.object)
    headers = {'ETag': self.object.etag}
    return Response(serializer.data, headers=headers)

وضع ، تصحيح ، حذف
يمكن إجراء فحص عام لتحديث أفعال HTTP في طريقة العرض dispatch أو ربما يتم سحبها إلى طريقة أخرى حيث ستحتاج إلى التحقق من تشغيل ETAG (راجع قسم الخيارات أدناه):

    header_etag = request.META.get('HTTP_IF_MATCH')
    if header_etag is None:
        return Response({'error': 'IF_MATCH header is required'}, status=400)

ثم تحقق أكثر تفصيلاً بعد استرداد الكائن لمعرفة ما إذا كان الطلب يعتقد أنه ينظر إلى العنصر الصحيح:

    if self.object.etag != header_etag:
        return Response({'error': 'object has been updated since you last saw it'}, status=412)

تمثيل فريد لإصدار مثيل

لا أعتقد أن التوليد الفعلي لـ ETag الخاص بالكائن يجب أن يكون مشكلة DRF. لقد كنت أختبر باستخدام وقت الحقبة الخاصة بحقل الكائن updated لكن يمكنني بسهولة أن أرى أنه يحتاج إلى أن يكون أكثر تعقيدًا.

أقترح أن يبحث DRF عن obj.etag افتراضيًا ولكنه قابل للتكوين باستخدام تدفق CBV العادي ، على سبيل المثال get_etag() و etag_var = 'get_my_objects_etag' .

سنحتاج أيضًا إلى فرض استرجاع ETAG من الكائنات كسلسلة نظرًا لأننا نقارن مع رأس ونحاول تفسير النوع سيكون مؤلمًا في أحسن الأحوال.

خيارات

  • الإعداد العالمي (كما هو الحال مع المتسلسلات ، إلخ) لتشغيل أو إيقاف تشغيل استخدام ETag.
  • إعدادان على طرق العرض:

    • use_etags (أو شيء مشابه) - قيمة منطقية

    • etag_var - سلسلة اسم دالة يمكننا getattr على الكائن المعني

ghickman - أود أن أرى سلوك تحديد ETags و LastModified يبدو مشابهًا للفئات الأخرى القابلة للتوصيل. بمعنى آخر. لديك شيء مثل:

class MyView(views.APIView):
    cache_lookup_classes = []

يجب أن تتعامل تواقيع التخزين المؤقت مع كل من ETags و LastModified ، وهناك شيئان مختلفان نريد توفيرهما:

  • حدد etag و / أو آخر تعديل مع وجود مثيل لكائن.
  • حدد بشكل استباقي etag و / أو آخر تعديل بالنظر إلى الطلب الوارد.

سيكون هناك BaseCacheLookup ، مع توقيعين للطريقة التي قد تبدو مثل:

.object_etag_and_last_modified(self, view, obj)
.preemptive_etag_and_last_modified(self, view, request, *view_kwargs, **view_kwargs)

بالنظر إلى الكائن ، يتم إرجاع مجموعتين من (etag, last modified) ، وقد يكون أي منهما ببساطة لا شيء.
إذا كان الطلب الوارد يحتوي على عنوان If-Modified-Since أو If-None-Match مطابق ، فسيتم إرجاع استجابة 304 Not Modified. إذا كانت الاستجابة الواردة تحتوي على مطابقة If-Match أو If-Unmodified-منذ ذلك الحين ، فسيتم إرجاع رد 412 فشل الشرط المسبق.

سيسمح هذا لـ CacheLookupClass بمطابقة التنفيذ الذي وصفته ، ولكن أيضًا المتغيرات الأخرى.

يمكنك أيضًا تطبيق عدة فئات بحث في ذاكرة التخزين المؤقت ، بمستوى دقة آخر تم تعديله ، على سبيل المثال ،
تضمين GlobalLastModifiedLookup بالإضافة إلى ObjectETagLookup . سيسمح ذلك للعرض بالعودة بشكل استباقي قبل إجراء أي استدعاءات لقاعدة البيانات إذا لم يتم إجراء أي عمليات كتابة منذ النسخة المخبأة. (حتى السياسات الأساسية مثل هذه يمكن أن تحدث فرقًا كبيرًا إذا كنت تستخدم التخزين المؤقت من جانب الخادم مع Varnish)

هل الجانب الصفي القابل للتوصيل من هذا يبدو معقولاً بالنسبة لك؟

لم أفكر في LastModified لأنني لا أستخدمه في تطبيقي الحالي ، لكن من المنطقي بالتأكيد تضمينه في ضوء الغرض منه.

تبدو الفئات القابلة للتوصيل فكرة رائعة ، خاصةً إذا قمنا بتضمين تطبيقات LastModified و ETag كأمثلة أساسية. تعجبني فكرة أن التخزين المؤقت لـ GET سيكون من السهل جدًا تشغيله مع الحد الأدنى من التغييرات في المشروع.

أفضل تقسيم etag والجيل الأخير المعدل إلى طريقتين (من هذه الأسماء) ، كما اقترحت ، تُرجع None عندما لا يتم تنفيذها. يمكن أن تختار الخلفيات الخلفية CacheLookup بعد ذلك تنفيذ أحدهما و / أو الآخر. يمكننا دائمًا توفير طريقة مساعدة للراحة (ربما cachable_obj_repr أو unique_obj_repr ربما؟) التي تجمع بين الاثنين إذا شعرت أنها ستكون مفيدة.

tl ؛ dr نعم ، يبدو جانب الفئة القابل للتوصيل معقولًا ويجب أن يوفر قدرًا أكبر من المرونة. يسعدني أن أبدأ في كتابة التصحيح لهذا الغرض.

أهلا بالجميع. إذا كنت مهتمًا ، فقد قمت بتطبيق نهج مختلف لدعم etag في مكتبة الإضافات الخاصة بي http://chibisov.github.io/drf-extensions/docs/

تضمين التغريدة يجب علينا حقًا إنهاء # 1019 ، لذلك لدينا مكان ما في المستندات لربط حزم مثل هذه.

تم إغلاق هذا بإغلاق # 1019 وتم إدراج حزمة

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

لسوء الحظ ، فإن التنفيذ والتوثيق الافتراضي لوظيفة Etag في ملحقات drf هو ببساطة خطأ وخطير عربات التي تجرها الدواب. يغير Etag إذا تغير _request_ ، وليس إذا تغير _response_. وهو بالضبط ما تريده للتخزين المؤقت من جانب الخادم ، وهو بالضبط ما لا تريده لـ Etag.

mbox سيكون أفضل شيء هو فتح مشكلة حول هذا الموضوع على ملحقات drf أو إذا كنت تعتقد أنها مشكلة "أساسية" في DRF مفتوحة هنا. يرجى ملاحظة أن اختبار الرسوب سيكون بداية جيدة لنا للنظر في المشكلة.

تضمين التغريدة
لقد قدمت للتو PR إلى ملحقات drf (https://github.com/chibisov/drf-extensions/pull/171) التي تتيح التحكم المتفائل في التزامن لمعالجة الموارد عبر واجهة برمجة تطبيقات DRF. إنها تستخدم تجزئة دلالية لجميع حقول الكائنات وقمت بتضمين تطبيق اختبار لأغراض العرض التوضيحي. تم اختباره ضد DRF> = 3.3.1 و django> = 1.8 مع Python 2.7، 3.4، 3.5.

شكرا

مجرد ملاحظة للقراء في المستقبل - لقد قمت بإنشاء حزمة صغيرة لاستخدام الديكور الشرطي من Django مع DRF. لذلك إذا كنت مهتمًا:
https://github.com/jozo/django-rest-framework-condition

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