Django-rest-framework: المسلسل المتداخل لا يتلقى سياق العرض

تم إنشاؤها على ١٣ فبراير ٢٠١٥  ·  26تعليقات  ·  مصدر: encode/django-rest-framework

_It is not stackoverflow question IMO، لذا إسمح لي إذا كان _

أحاول استخدام المسلسلات المتداخلة ، أعلم أنه من الصعب مناقشتها نظرًا لأن لدينا العديد من المشكلات في v2-Branch. أريد أن يستخدم حقل المُسلسل المتداخل افتراضيًا استنادًا إلى المشروع المحدد.

تم تقديم معرف المشروع في QUERY_PARAMS ويتم تطبيقه في perform_create كما يجب الآن ، في v3-الفرع. لكني أحتاج إلى مشروع في بعض الحقول المتسلسلة المتداخلة قبل الحفظ - أرغب في تقديم القيم الافتراضية للكائن في البيانات الوصفية للمسلسل ، حتى يتمكن المستخدم من تغيير بعض الأشياء ، والتي يمكن أخذها اختياريًا من كائن المشروع.

لذلك ، أقوم بملء context بـ get_serializer_context بكائن المشروع. ويجب عليّ فقط إعادة كتابة __init__ في المسلسل المتداخل لتعيين الإعدادات الافتراضية ، أليس كذلك؟

المشكلة هي أن المسلسل المتداخل لا يتلقى context ولا parent في __init__ . يبدو أنه لا يتلقى السياق على الإطلاق! لذلك ، يجب أن يكون تراجعًا منذ طلب السحب 497 .

أعتقد أنه ليس انحدارًا ، إنه أشبه بتغيير في التصميم ، لكنني حقًا أحتاج إلى سياق لأتمكن من تغيير سلوك المسلسل!

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

أعتقد أن أحد الحلول قد يكون دائمًا إنشاء مثيل ChildSerializer المتداخل في طريقة __init__ للطريقة ParentSerializer بدلاً من إعلان الحقل ، ثم يمكن إعادة توجيه السياق يدويًا.

مثله:

class ChildSerializer(serializers.Serializer):
    ...

class ParentSerializer(serializers.Serializer):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.fields['child'] = ChildSerializer(context=self.context)

يبدو أن هذا يعمل في اختبار أولي. لست متأكدًا مما إذا كان هناك أي مشكلة مع هذا.

ال 26 كومينتر

لم يتم (لا يمكن) تمرير السياق إلى الحقول (أو المسلسل المتداخل) عند نقطة التهيئة ، لأنه يتم تهيئتها عندما يتم الإعلان عنها في المسلسل الأصلي ...

class MySerializer(Serializer):
    child = ChildSerializer()  <--- We've just initialized this.

الأفضل هو أداء أي سلوك كهذا في MySerializer.__init__ ، على سبيل المثال ...

def __init__(self, *args, **kwargs):
    super(MySerializer, self).__init__(*args, **kwargs)
    self.fields['child'].default = ...

في هذه المرحلة ، يمكنك _do_ الوصول إلى السياق.

إذا كنت تريد حقًا ، يمكنك تنفيذ بعض الإجراءات عند النقطة التي يصبح فيها الحقل مرتبطًا بأصله ...

class ChildSerializer(Serializer):
    def bind(self, *args, **kwargs):
        super(ChildSerializer, self).bind(*args, **kwargs)
        # do stuff with self.context.

يجب اعتبار هذا واجهة برمجة تطبيقات خاصة ، ويفضل النمط الأصلي __init__ المذكور أعلاه.

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

لذلك ، يبدو أن bind يجب أن يكون جيدًا.

يجب اعتبار هذا واجهة برمجة تطبيقات خاصة ، ويفضل النمط الأصلي __init__ المذكور أعلاه.

ولكن نظرًا لأنه لا يمكننا استخدام __init__ ، لأنه لا يمكننا الوصول إلى جميع البيئة المتاحة ، التي تم إنشاؤها بواسطة العرض في الوقت الحالي ، يجب أن يكون لدينا طريقة API عامة ، والتي تسمى في الحقل (مُسلسل) عندما يكون لدينا كل الأشياء متوفرة. مثل initialize كان.

هل يعمل مع DRF 2؟

إنه سياق مؤسف لم يعد ينتشر إلى المسلسلات المتداخلة.

إنه سياق مؤسف لم يعد ينتشر إلى المسلسلات المتداخلة.

من اين حصلت على ذلك ؟ Afaik ، سياق _ هو نشر إلى المسلسلات المتداخلة.

xordoquy هذا غريب - لقد قمت بعمل اختبار ضد أحدث إصدار من drf ولا يمكنني إعادة إنتاج المشكلة :) علاوة على ذلك لا يمكنني إعادة إنتاجها مرة أخرى في الكود الخاص بي. تم حل المشكلة.

xiaohanyu في الواقع لقد وجدت هذه المشكلة مرة أخرى. وهذا غريب نوعا ما:

>>> serializer
Out[12]: 
# Note there is context passed in constructor
CouponSerializer(<Coupon: Coupon Coupon #0 for offer Offer #0000>, context={'publisher': <User: John ZusPJRryIzYZ>}):
    id = IntegerField(label='ID', read_only=True)
    title = CharField(max_length=100, required=True)
    short_title = CharField(max_length=30)
    offer_details = OfferLimitedSerializer(read_only=True, source='offer'):
        id = IntegerField(label='ID', read_only=True)
        title = CharField(help_text='The Offer Title will be used for the Network, Advertisers and Publishers to identify the specific offer within the application.', read_only=True)       
        status_name = CharField(read_only=True, source='get_status_display')
        is_access_limited = SerializerMethodField()    
    exclusive = BooleanField(required=False)    
    categories_details = OfferCategorySerializer(many=True, read_only=True, source='categories'):
        id = IntegerField(read_only=True)
        category = CharField(read_only=True, source='code')
        category_name = CharField(read_only=True, source='get_code_display')    

# all fields except one got context propagated
>>> [f.field_name for f in serializer.fields.values() if not f.context]
Out[20]: 
['offer_details']

# offer_details is no different than categories_details, both are nested, read only, model serializers..
>>> serializer.fields['categories_details'].context
Out[21]: 
{'publisher': <User: John ZusPJRryIzYZ>}

# lets look inside problematic serializer
>>> offer_details = serializer.fields['offer_details']
>>> offer_details
Out[25]: 

OfferLimitedSerializer(read_only=True, source='offer'):
    id = IntegerField(label='ID', read_only=True)
    title = CharField(help_text='The Offer Title will be used for the Network, Advertisers and Publishers to identify the specific offer within the application.', read_only=True)    
    status_name = CharField(read_only=True, source='get_status_display')
    url = SerializerMethodField()
    is_access_limited = SerializerMethodField()
>>> offer_details.context
Out[23]: 
{}
>>> offer_details._context
Out[24]: 
{}
# ! surprisingly context is available inside fields... but not in the parent
>>> offer_details.fields['is_access_limited'].context
Out[26]: 
{'publisher': <User: John ZusPJRryIzYZ>}

# context is available in all of them!
>>> [x.field_name for x in offer_details.fields.values() if not x.context]
Out[27]: 
[]

tomchristie آسف على الإزعاج ، لكن ربما لديك أي أفكار كيف يكون ذلك ممكنًا؟

في غضون ذلك ، أجبرت على استخدام هذا الاختراق لحل مشكلة:

class Serializer(serializers.Serializer):

    def __init__(self, *args, **kwargs):
        super(Serializer, self).__init__(*args, **kwargs)
        # propagate context to nested complex serializers
        if self.context:
            for field in six.itervalues(self.fields):
                if not field.context:
                    delattr(field, 'context')
                    setattr(field, '_context', self.context)

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

اتضح أنه يحدث بسبب التعقيد mro ، حيث تكون الفئات المتعددة أبناء للمسلسلات. شئ مثل هذا

class MyMixin(serializers.Serializer):
   # some code within __init__, calling parent too

class MyModelSerializer(serializers.ModelSerializer):
   # some code within __init__, calling parent too

class MyProblematicSerializer(MyModelSerializer, MyMixin)
    # this one will not receive context somehow.
     pass

على أي حال ، أعتقد أنه يمكن اعتباره مشكلة محلية ..

شكرا على ردود الفعل 👍

xordoquytomchristie في الواقع أصبحت المشكلة غريبة حقًا :) عندما تصل إلى self.context في مشكلة متسلسلة متجاوزة مع ظهور سياق مفقود. لقد حاولت القيام بذلك في عقار fields بدون حظ. هنا testcase:

def test_serializer_context(self):
        class MyBaseSerializer(serializers.Serializer):
            def __init__(self, *args, **kwargs):
                super(MyBaseSerializer, self).__init__(*args, **kwargs)
                x = 0
                if self.context.get('x'):
                    x = self.context['x']

        class SubSerializer(MyBaseSerializer):
            char = serializers.CharField()
            integer = serializers.IntegerField()

        class ParentSerializer(MyBaseSerializer):
            with_context = serializers.CharField()
            without_context = SubSerializer()

        serializer = ParentSerializer(data={}, context={'what': 42})
        assert serializer.context == {'what': 42}
        assert serializer.fields['with_context'].context == {'what': 42}
        assert serializer.fields['without_context'].context == {'what': 42}

لكن هذا سوف يمر. يجدر الإشارة في المصادر إلى أن الوصول إلى السياق بأساليب مفرطة قد يكون مشكلة ...

def test_serializer_context(self):
        class MyBaseSerializer(serializers.Serializer):
            <strong i="12">@property</strong>
            def fields(self):
                fields = super(MyBaseSerializer, self).fields
                x = 0
                if self.root.context.get('x'):
                    x = 1
                return fields


        class SubSerializer(MyBaseSerializer):
            char = serializers.CharField()
            integer = serializers.IntegerField()

        class ParentSerializer(MyBaseSerializer):
            with_context = serializers.CharField()
            without_context = SubSerializer()

        serializer = ParentSerializer(data={}, context={'what': 42})
        assert serializer.context == {'what': 42}
        assert serializer.fields['with_context'].context == {'what': 42}
        assert serializer.fields['without_context'].context == {'what': 42}

لأكون واضحًا - ما أفعله هنا هو تغيير سلوك الحقول بناءً على السياق.

محدث: حتى الرمز الأخير لا يمكن الاعتماد عليه في بعض الحالات. تبين أن لمس السياق أمر خطير.

من المؤسف أن __init__ لا يملك حق الوصول إلى السياق. إذا أراد المرء إنشاء حقول ديناميكيًا في المسلسل بناءً على شيء ما في السياق ، فأين ستفعل ذلك؟

لا يبدو أنه يعمل في bind كما تم اقتراحه أعلاه. على سبيل المثال self.fields['asdf'] = serializers.CharField() . أفترض أن الحقول قد تم تقييمها بالفعل عند استدعاء bind .

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

أعتقد أن هذا لن يكون مشكلة إذا تم إجراء التداخل كحقل ، بدلاً من استدعاء المسلسل مباشرة.

مثله:

class ChildSerializer(serializers.Serializer):
    ...

class ParentSerializer(serializers.Serializer):
    child = serializers.NestedField(serializer=ChildSerializer)

ثم يمكن لـ ChildSerializer الوصول إلى السياق في __init__ ، نظرًا لأنه لا يتم إنشاء مثيل له مباشرةً في إعلان الحقل في ParentSerializer .

إذا أراد المرء إنشاء حقول ديناميكيًا في المسلسل بناءً على شيء ما في السياق ، فأين ستفعل ذلك؟

دعنا نتحدث عن هذا في سياق مثال محدد. ابتكر حالة استخدام بسيطة لطيفة ويمكننا اكتشاف أفضل طريقة لمعالجتها.

أعتقد أن هذا لن يكون مشكلة إذا تم إجراء التداخل كحقل ، بدلاً من استدعاء المسلسل مباشرة.

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

tomchristie شكرا على الرد.

إحدى حالات الاستخدام التي أمتلكها الآن هي التبديل بين مجموعتين مختلفتين من الحقول في جهاز تسلسلي تابع متداخل بناءً على خاصية المستخدم المسجل حاليًا.

يجب ألا يرى مستخدمو النوع "أ" الحقول ذات الصلة بمستخدمي النوع "ب" ، والعكس صحيح.

تبدو هكذا:

class ChildSerializer(serializers.Serializer):
  # relevant for all users
  name = serializers.CharField()

  # only relevant for users of Type A
  phone = serializers.CharField()

  # only relevant for users of Type B
  ssn = serializers.CharField()

لكنني أقوم بتعديل الحقول بانتظام بعدة طرق مختلفة ، في كل من نماذج api وكذلك في شكل html ، باستخدام متسلسلات drf و / أو نماذج django. إضافة الحقول ديناميكيًا ، وإزالة الحقول ، وتعديل السمات ، المثال أعلاه بعيد عن الطريقة الوحيدة. لم أضطر أبدًا إلى فعل ذلك مع طفل متداخل من قبل ، وقد شعرت بالحيرة تمامًا بسبب هذا.

tomchristie إن حالة الاستخدام النموذجية الخاصة بي هي التحكم في ما إذا كان الحقل مطلوبًا أم لا بناءً على السياق (تخيل مُسلسِلًا للمستخدم والمسؤول ، حيث لا يحتاج أحدهما إلى توفير معرف المستخدم منذ تمريره عبر السياق.) استخدم حلاً من مشاركاتي السابقة في هذا الموضوع.

أعتقد أن أحد الحلول قد يكون دائمًا إنشاء مثيل ChildSerializer المتداخل في طريقة __init__ للطريقة ParentSerializer بدلاً من إعلان الحقل ، ثم يمكن إعادة توجيه السياق يدويًا.

مثله:

class ChildSerializer(serializers.Serializer):
    ...

class ParentSerializer(serializers.Serializer):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.fields['child'] = ChildSerializer(context=self.context)

يبدو أن هذا يعمل في اختبار أولي. لست متأكدًا مما إذا كان هناك أي مشكلة مع هذا.

كان سيقترح نفس الشيء ، نعم.

حسنًا ، لم ينجح الأمر بالنسبة لي في بعض الحالات. ربما بسبب الميراث المتعدد.

في يوم الأربعاء ، 12 تشرين الأول (أكتوبر) 2016 ، الساعة 2:56 مساءً +0200 ، كتب "Tom Christie" [email protected] :

كان سيقترح نفس الشيء ، نعم.

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

أواجه نفس المشكلة ، عندما قمت بتعيين السمة default ( CurrentUserDefault() في حالتي) إلى حقل المسلسل (المتداخل) الذي صنف الأسلوب __init__ الذي يعالج السمة self.context KeyError ، يظهر request في السياق (الذي لا يحتوي على أي شيء ، أي أنه لم يتم تمريره من الأصل).
رمز المثال:

class UserSerializer(serializers.ModelSerializer):
# ...
    def __init__(self, *args, **kwargs):
        kwargs.pop('fields', None)
        super().__init__(*args, **kwargs)
        if 'list' in self.context: # Once I remove this, it will work
            self.fields['friend_count'] = serializers.SerializerMethodField()
# ...

class CommentSerializer(serializers.ModelSerializer):
    person = UserSerializer(read_only=True, default=serializers.CurrentUserDefault())
# ...

سجل الخطأ:

Environment:


Request Method: POST
Request URL: http://127.0.0.1:8000/api/comments/98/

Django Version: 1.9.7
Python Version: 3.4.3
Installed Applications:
['django.contrib.admin',
 'django.contrib.auth',
 'django.contrib.contenttypes',
 'django.contrib.sessions',
 'django.contrib.messages',
 'django.contrib.staticfiles',
 'django.contrib.sites',
 'rest_framework',
 'rest_framework.authtoken',
 'generic_relations',
 'decorator_include',
 'allauth',
 'allauth.account',
 'allauth.socialaccount',
 'allauth.socialaccount.providers.facebook',
 'allauth.socialaccount.providers.google',
 'phonenumber_field',
 'bootstrap3',
 'stronghold',
 'captcha',
 'django_settings_export',
 'main']
Installed Middleware:
['django.middleware.security.SecurityMiddleware',
 'django.contrib.sessions.middleware.SessionMiddleware',
 'django.middleware.common.CommonMiddleware',
 'django.middleware.csrf.CsrfViewMiddleware',
 'django.contrib.auth.middleware.AuthenticationMiddleware',
 'django.contrib.auth.middleware.SessionAuthenticationMiddleware',
 'django.contrib.messages.middleware.MessageMiddleware',
 'django.middleware.clickjacking.XFrameOptionsMiddleware',
 'stronghold.middleware.LoginRequiredMiddleware']



Traceback:

File "/home/mikisoft/django-dev/lib/python3.4/site-packages/django/core/handlers/base.py" in get_response
  149.                     response = self.process_exception_by_middleware(e, request)

File "/home/mikisoft/django-dev/lib/python3.4/site-packages/django/core/handlers/base.py" in get_response
  147.                     response = wrapped_callback(request, *callback_args, **callback_kwargs)

File "/home/mikisoft/django-dev/lib/python3.4/site-packages/django/views/decorators/csrf.py" in wrapped_view
  58.         return view_func(*args, **kwargs)

File "/home/mikisoft/django-dev/lib/python3.4/site-packages/django/views/generic/base.py" in view
  68.             return self.dispatch(request, *args, **kwargs)

File "/home/mikisoft/django-dev/lib/python3.4/site-packages/rest_framework/views.py" in dispatch
  466.             response = self.handle_exception(exc)

File "/home/mikisoft/django-dev/lib/python3.4/site-packages/rest_framework/views.py" in dispatch
  463.             response = handler(request, *args, **kwargs)

File "/home/mikisoft/django-dev/lib/python3.4/site-packages/rest_framework/generics.py" in post
  246.         return self.create(request, *args, **kwargs)

File "/home/mikisoft/django-dev/lib/python3.4/site-packages/rest_framework/mixins.py" in create
  20.         serializer.is_valid(raise_exception=True)

File "/home/mikisoft/django-dev/lib/python3.4/site-packages/rest_framework/serializers.py" in is_valid
  213.                 self._validated_data = self.run_validation(self.initial_data)

File "/home/mikisoft/django-dev/lib/python3.4/site-packages/rest_framework/serializers.py" in run_validation
  407.         value = self.to_internal_value(data)

File "/home/mikisoft/django-dev/lib/python3.4/site-packages/rest_framework/serializers.py" in to_internal_value
  437.                 validated_value = field.run_validation(primitive_value)

File "/home/mikisoft/django-dev/lib/python3.4/site-packages/rest_framework/serializers.py" in run_validation
  403.         (is_empty_value, data) = self.validate_empty_values(data)

File "/home/mikisoft/django-dev/lib/python3.4/site-packages/rest_framework/fields.py" in validate_empty_values
  453.             return (True, self.get_default())

File "/home/mikisoft/django-dev/lib/python3.4/site-packages/rest_framework/fields.py" in get_default
  437.                 self.default.set_context(self)

File "/home/mikisoft/django-dev/lib/python3.4/site-packages/rest_framework/fields.py" in set_context
  239.         self.user = serializer_field.context['request'].user

Exception Type: KeyError at /api/comments/98/
Exception Value: 'request'

يفتقر الحقل المُضاف إلى بعض الأشياء التي يقوم بها المُسلسل من خلال الفئات الوصفية. الأمر متروك لك لتعيينهم.

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

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

تمام. بالنسبة للملاحظة الأخيرة ، أريد فقط أن أشير إلى أنه مثلما يظهر في سجل الأخطاء ، فإنه لا يظهر بطريقة __init__ ، ولكن في كائن CurrentUserDefault() (في set_context طريقة). لكن تأكد من ظهوره أيضًا في __init__ إذا كان هناك استدعاء مباشر لمعامل السياق ، أي بدون التحقق من وجوده (لأن السياق بأكمله فارغ ، لأنه لم يتم تجاوزه).
أيضًا ، أود تكرار ما خلص إليه شخص آخر أعلاه - في حالة عدم وجود تداخل (وعندما يتم استخدام السياق في طريقة إنشاء مثيل) ، يعمل كل شيء كما هو متوقع.

كانت هناك مشكلة في نشر السياق للأطفال ، يجب حلها في https://github.com/encode/django-rest-framework/pull/5304 أعتقد أنه كان يجب أن يكون هناك العديد من المشكلات المتعلقة بالتخزين المؤقت None كجذر للمسلسلات الفرعية التي يجب حلها باستخدام هذا العلاقات العامة.

واجهت هذه المشكلة مؤخرًا. هذا هو الحل الذي نجح معي:

class MyBaseSerializer(serializers.HyperlinkedModelSerializer):

    def get_fields(self):
        '''
        Override get_fields() method to pass context to other serializers of this base class.

        If the context contains query param "omit_data" as set to true, omit the "data" field
        '''
        fields = super().get_fields()

        # Cause fields with this same base class to inherit self._context
        for field_name in fields:
            if isinstance(fields[field_name], serializers.ListSerializer):
                if isinstance(fields[field_name].child, MyBaseSerializer):
                    fields[field_name].child._context = self._context

            elif isinstance(fields[field_name], MyBaseSerializer):
                fields[field_name]._context = self._context

        # Check for "omit_data" in the query params and remove data field if true
        if 'request' in self._context:
            omit_data = self._context['request'].query_params.get('omit_data', False)

            if omit_data and omit_data.lower() in ['true', '1']:
                fields.pop('data')

        return fields

في ما سبق ، قمت بإنشاء فئة أساسية للمسلسل تتجاوز get_fields() وتمرر self._context إلى أي مُسلسل فرعي له نفس الفئة الأساسية. بالنسبة إلى ListSerializers ، أرفق السياق بالجزء الفرعي منه.

بعد ذلك ، أتحقق من وجود معلمة استعلام "omit_data" وأزل حقل "البيانات" إذا طُلب ذلك.

آمل أن يكون هذا مفيدًا لأي شخص لا يزال يبحث عن إجابات لهذا.

أعلم أن هذا سلسلة رسائل قديمة ، لكنني أردت فقط أن أشارك أنني أستخدم مزيجًا من __init__ وربطه في ملف mixin المخصص الخاص بي لتصفية مجموعة طلبات البحث بناءً على الطلب (في السياق). يفترض هذا المزيج أن طريقة get_objects_for_user موجودة في مجموعة الاستعلام ، أو تستخدم guardian.shortcuts.get_objects_for_user. إنه يعمل بشكل رائع مع المسلسلات المتداخلة ، أيضًا عند النشر أو التصحيح.

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