Django-rest-framework: يحتوي Serializer DateTimeField على معلومات منطقة زمنية غير متوقعة

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

لدي TIME_ZONE = 'Asia/Kolkata' و USE_TZ = True في إعداداتي.

عندما أقوم بإنشاء كائن جديد باستخدام واجهة برمجة التطبيقات القابلة للتصفح ، يعرض المسلسل الكائن الذي تم إنشاؤه حديثًا بأوقات زمنية تتخلف +5:30 ، مما يشير إلى المنطقة الزمنية. تقوم قاعدة البيانات بتخزين الأوقات بالتوقيت العالمي المنسق (UTC).

السلوك غير المتوقع هو أنه عندما يتم إجراء تسلسل للكائن مرة أخرى لاحقًا ، تكون جميع أوقات البيانات بتنسيق UTC مع زائدة Z . وفقًا لمستندات Django في المنطقة الزمنية الحالية والافتراضية ، أتوقع أن يقوم المسلسل بتحويل أوقات البيانات إلى المنطقة الزمنية الحالية ، والتي يتم تعيينها افتراضيًا على المنطقة الزمنية الافتراضية ، والتي يتم تعيينها بواسطة TIME_ZONE = 'Asia/Kolkata' .

هل فاتني شيء؟

Needs further review

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

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

ال 34 كومينتر

سألت عن تجاوز سعة المكدس والاستنتاج هو أن المنطقة الزمنية الحالية تستخدم فقط لأوقات التاريخ التي يوفرها المستخدم ، حيث يتم تسلسل التاريخ والوقت كما هو بعد التحقق من الصحة (أي بعد الإنشاء أو التحديث). من وثائق Django ، أجد صعوبة في تصديق أن هذا هو السلوك المقصود ، لكن هذه مشكلة في Django نفسها وليست مع Rest Framework ، لذلك سأغلق هذه المشكلة.

مرحبا tomchristie ،

أعتقد أن هذا خطأ DRF.
IMHO ، الاستخدام الطبيعي لـ DRF هو استخدامه كمخرج مثل قالب django.
في نموذج django ، يتم عرض المنطقة الزمنية بشكل صحيح ، لماذا لا يحترم برنامج drf المتسلسل إعداد المنطقة الزمنية django؟

أهلا،

بالنظر إلى الكود في فئة fields.py عند DatetimeField class ، اكتشفت أن إعداد المنطقة الزمنية لـ Django يعتبر جيدًا فقط للقيمة الداخلية ( to_internal_value() ).

لقد رأيت أن استخدام جهاز التسلسل النموذجي مثل هذا:

class MyModelSerializer(ModelSerializer):

    class Meta:
        model = MyModel
        depth = 1
        fields = ('some_field', 'my_date_time_field')

للحقل my_date_time_field (أعتقد أنه حقل DateTimeField :)) المنطقة الزمنية للتمثيل هي بلا للافتراضي ( to_representation() ).

بعبارة أخرى ، إذا لم أكن مخطئًا ، فلن يتم اعتبار المنطقة الزمنية لـ Django إلا عند كتابة القيمة في الواجهة الخلفية للتخزين.

IMHO أعتقد أن القيمة المرجعة to_representation() يجب أن تكون على النحو التالي:
return self.enforce_timezone(value).strftime(output_format)
وفقًا لإعداد Django USE_TZ .

أكتب طلب سحب لهذا.

تشاو
فالنتينو

vpistis سيكون من الأسهل مراجعة هذا إذا كان بإمكانك إعطاء مثال عن سلوك واجهة برمجة التطبيقات الذي تراه حاليًا ، وما تتوقع رؤيته (بدلاً من مناقشة جوانب التنفيذ أولاً)

عيّن TIME_ZONE = 'Asia/Kolkata' وأنشئ مُسلسلاً للنماذج بحقل تاريخ واحد ووقت واحد ، appointment .

أثناء الإنشاء / التحديث ، أرسل:

{
    "appointment": "2016-12-19T10:00:00"
}

و ارجع:

{
    "appointment": "2016-12-19T10:00:00+5:30"
}

ولكن إذا استعدت هذا الكائن أو أدرجته مرة أخرى ، فستحصل على:

{
    "appointment": "2016-12-19T04:30:00Z"
}

أثناء الإنشاء ، إذا لم يتم تحديد Z ، يفترض DRF أن العميل يستخدم المنطقة الزمنية المحددة بواسطة TIME_ZONE ويعيد وقتًا منسقًا لتلك المنطقة الزمنية (عن طريق إضافة +5:30 في النهاية ، والذي سيكون في الواقع غير صالح إذا كان الوقت الذي قدمه العميل). قد يكون من المنطقي أكثر إذا أعادت عمليات الوصول المستقبلية أيضًا وقتًا منسقًا لتلك المنطقة الزمنية ، لذلك كانت الاستجابة أثناء الاسترداد / القائمة هي نفسها أثناء الإنشاء / التحديث.

هناك أيضًا مسألة ما إذا كان سيتم إرجاع الأوقات في المنطقة الزمنية التي تم تكوينها عند توفير Z اللاحقة أثناء الإنشاء / التحديث ، مثل إرسال:

{
    "appointment": "2016-12-19T04:30:00Z"
}

عائدات:

{
    "appointment": "2016-12-19T10:00:00+5:30"
}

سأكون مع هذا ، لأنه يحافظ على الاستجابة متسقة مع الاستجابة للقوائم / الاسترجاع.

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

عيّن TIME_ZONE = 'Asia / Kolkata' وأنشئ مُسلسلًا نموذجيًا مع حقل واحد للتاريخ والوقت ، موعد.

أثناء الإنشاء / التحديث ، أرسل:

{
"موعد": "2016-12-19T10: 00: 00"
}
و ارجع:

{
"موعد": "2016-12-19T10: 00: 00 + 5: 30"
}
ولكن إذا استعدت هذا الكائن أو أدرجته مرة أخرى ، فستحصل على:

{
"موعد": "2016-12-19T04: 30: 00Z"
}

thanx @ jonathan-golorry هذا هو السلوك الدقيق الذي أراه بالفعل.
بالنسبة لي ، يجب أن يكون السلوك على هذا النحو (باستخدام مثال @ jonathan-golorry :)):

أثناء الإنشاء / التحديث باستخدام DATETIME_FORMAT الافتراضي ، أرسل:

{
    "appointment": "2016-12-19T10:00:00"
}

و ارجع:

{
    "appointment": "2016-12-19T10:00:00+5:30"
}

إذا قمت باسترداد هذا الكائن أو سرده مرة أخرى ، فستحصل على:

{
    "appointment": "2016-12-19T10:00:00+5:30"
}

ربما يجب أن يكون IMHO هو إعداد DRF لإدارة هذا السلوك ، على سبيل المثال ، إعداد لفرض تمثيل DateTimeField بالمنطقة الزمنية الافتراضية.

شكرا جزيلا تومكريستي

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

بالنسبة إلى تطبيق ويب إنتاجي يستخدم DRF 3.4.6 ، تم حل هذا الحل البديل:
https://github.com/vpistis/django-rest-framework/commit/be62db9080b19998d4de3a1f651a291d691718f6

إذا أراد أي شخص تقديم طلب سحب يتضمن إما:

  • يتضمن فقط حالات الاختبار الفاشلة ، أو ...
  • حالة الاختبار + الإصلاح

سيكون ذلك موضع ترحيب كبير.

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

شكرا

إذا كنت تبحث عن تعديل إعدادات الاختبار العامة ، فهي موجودة هنا .

إذا كنت تحاول تجاوز الإعدادات أثناء الاختبار ، فيمكنك استخدام مصمم الديكور override_settings .

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

ستكون الخطوة الأولى هنا هي كتابة حالة اختبار فاشلة يمكننا إضافتها إلى مجموعة الاختبار الحالية.
ستكون الخطوة التالية هي بدء إصلاح لهذه الحالة :)

أهلا،
بالنسبة لي ، هذه حالة اختبار لهذه الميزة

class TestDateTimeFieldTimeZone(TestCase):
    """
    Valid and invalid values for `DateTimeField`.
    """
    from django.utils import timezone

    valid_inputs = {
        '2001-01-01 13:00': datetime.datetime(2001, 1, 1, 13, 00, tzinfo=timezone.get_default_timezone()),
        '2001-01-01T13:00': datetime.datetime(2001, 1, 1, 13, 00, tzinfo=timezone.get_default_timezone()),
        '2001-01-01T13:00Z': datetime.datetime(2001, 1, 1, 13, 00, tzinfo=timezone.get_default_timezone()),
        datetime.datetime(2001, 1, 1, 13, 00): datetime.datetime(2001, 1, 1, 13, 00, tzinfo=timezone.get_default_timezone()),
        datetime.datetime(2001, 1, 1, 13, 00, tzinfo=timezone.UTC()): datetime.datetime(2001, 1, 1, 13, 00,
                                                                                        tzinfo=timezone.get_default_timezone()),
        # Django 1.4 does not support timezone string parsing.
        '2001-01-01T13:00Z': datetime.datetime(2001, 1, 1, 13, 00, tzinfo=timezone.get_default_timezone())
    }
    invalid_inputs = {}
    outputs = {
        # This is not simple, for now I suppose TIME_ZONE = "Europe/Rome"
        datetime.datetime(2001, 1, 1, 13, 00, tzinfo=timezone.get_default_timezone()): '2001-01-01T13:00:00+01:00',
        datetime.datetime(2001, 1, 1, 13, 00, ): '2001-01-01T13:00:00+01:00',
    }

    field = serializers.DateTimeField()

في مفترقتي ، أستخدم بعض الحيل للحصول على الأوقات في المنطقة الزمنية الصحيحة الخاصة

آمل أن يساعد هذا :)

أرى أن هذا مغلق ولكني أقوم بتشغيل drf 3.6.3 وفي قاعدة بيانات postgres لدي هذا الطابع الزمني "2017-07-12 14: 26: 00-06" ولكن عندما أحصل على البيانات باستخدام ساعي البريد أحصل على هذا "الطابع الزمني" : "2017-07-12T20: 26: 00Z". يبدو أنها تضيف على -06 ساعة.

تستخدم إعدادات django الخاصة بي tzlocal لتعيين المنطقة الزمنية TIME_ZONE = str(get_localzone()) . لذلك تم تعيين المنطقة الزمنية عند بدء التشغيل.

أنا أستخدم النموذج الأساسي المتسلسل

class SnapshotSerializer(serializers.ModelSerializer):
    class Meta:
        model = Snapshot
        resource_name = 'snapshot' 
        read_only_fields = ('id',)
        fields = ('id', 'timestamp', 'snapshot')

هل فاتني شيء؟

غير مغلق ، لا يزال مفتوحًا :)
"الزر المغلق" الأحمر الذي تراه هو لمشكلة المرجع.
.. وأنت على حق ، "الخطأ" لا يزال موجودًا ؛ (
تم تغيير المعلم من 3.6.3 إلى 3.6.4.

حسنا. شكرا لك!

في 12 تموز (يوليو) 2017 ، 5:10 مساءً ، "فالنتينو بيستيس" [email protected]
كتب:

غير مغلق ، لا يزال مفتوحًا :)
"الزر المغلق" الأحمر الذي تراه هو لمشكلة المرجع.
.. وأنت على حق ، "الخطأ" لا يزال موجودًا ؛ (
تم تغيير المعلم من 3.6.3 إلى 3.6.4.

-
أنت تتلقى هذا لأنك علقت.
قم بالرد على هذا البريد الإلكتروني مباشرة ، وقم بعرضه على GitHub
https://github.com/encode/django-rest-framework/issues/3732#issuecomment-314923582 ،
أو كتم الخيط
https://github.com/notifications/unsubscribe-auth/AIMBTcx-6PPbi_SOqeLCjeWV1Rb59-Ohks5sNVJ0gaJpZM4G0aRE
.

أهلا،

لست متأكدًا مما إذا كان هذا مرتبطًا تمامًا بالسؤال الأصلي ، ولكن هل يجب أن يحترم DRF أي تجاوزات للمنطقة الزمنية يتم تعيينها ، وفقًا لـ https://docs.djangoproject.com/en/1.11/ref/utils/#django. uses.timezone.activate ؟

لدي نظام يرتبط فيه المستخدمون بمنطقة زمنية ، وتتلقى واجهة برمجة التطبيقات (API) أوقاتًا غير صحيحة. أتوقع أن أكون قادرًا على تحويل تلك الأوقات إلى المنطقة الزمنية للمستخدم الحالي ، لكنني لاحظت أن ../rest_framework/fields.py يطبق المنطقة الزمنية الافتراضية (أي تلك الموجودة في ملف إعداد django:

    def enforce_timezone(self, value):
        field_timezone = getattr(self, 'timezone', self.default_timezone())

        if (field_timezone is not None) and not timezone.is_aware(value):
            try:
                return timezone.make_aware(value, field_timezone)

[...]

    def default_timezone(self):
        return timezone.get_default_timezone() if settings.USE_TZ else None

هل يجب فعلاً استخدام timezone.get_current_timezone() كتفضيل في حالة تعيين التطبيق لتجاوز ، كما في حالتي؟

مرحبًا RichardForshaw التي تبدو وكأنها مشكلة مميزة ، لكن نفس لعبة ball park بالتأكيد.

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

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

لكن نعم ، هناك تناقض هنا يجب معالجته. (هل ذكرت ترحيب PRs؟ 🙂)

يجب أن يكون carltongibson / django-filter # 750 مناسبًا هنا. لقد أسست في الأصل معالجة المنطقة الزمنية لـ django-filter على DRF ، لذلك يمكن بسهولة تطبيق التغييرات في 750 هنا.

آسف على مبتدئ ولكن ما المشكلة هنا بالضبط؟ الطابع الزمني في قاعدة بيانات psql الخاص بي صحيح وتم تعيين Django لاستخدام المنطقة الزمنية الصحيحة. هل هناك إعدادات DRF لمجرد عدم تحويل الطوابع الزمنية؟

مرحبًا michaelaelise - إذا نظرت إلى مثال البيانات (بالقرب من الجزء العلوي):

  1. إنهم يرسلون تاريخًا ووقتًا بدون معلومات المنطقة الزمنية. (هذه خطوة سيئة في كتابي).
  2. يقوم الخادم بتطبيق منطقته الزمنية المحلية ويعود على هذا النحو ( +5:30 في هذه الحالة)
  3. ولكن لاحقًا ، عندما تجلبه ، سيعود إلى UTC ( Z ، لأفترض لـ "Zulu").

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

لكن هناك القليل من التناقض ، بالتأكيد يجب أن يكون للنسقين 2 و 3 نفس التنسيق؟ (على الرغم من أن العميل سيقبل ، بشكل صحيح ، أيًا منهما كقيم مكافئة.)

أنا أميل إلى إغلاق هذا.

  • لا يوجد خطأ منطقي هنا.

    • هذه هي نفس الوقت: "2016-12-19T10:00:00+5:30" و "2016-12-19T04:30:00Z" - إلى حد ما ، من يهتم بكيفية عودتهم؟

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

يسعدني إلقاء نظرة على العلاقات العامة ولكني لست متأكدًا من أنني أريد حقًا اعتبار هذا _مشكلة مفتوحة_.

أوه ، لم أكن أدرك أنه في رسالتي الأصلية في موضوع هذا العدد ، كان الحرف "Z" يعني ذلك.
إذن DRF يقوم بتحويل التاريخ والوقت المدرك إلى UTC ليتم التعامل معه بواسطة واجهة المستخدم / المتصل؟
شكرا لك على هذا الإيضاح.

شيء أخير.
ماذا لو أردنا إرجاع "2016-12-19T10: 00: 00 + 5: 30" لأننا نقوم بالاستقصاء عن أجهزة في مناطق زمنية مختلفة.
هل يمكن أن يكون هذا إعدادًا "RETURN_DATETIME_WITH_TIMEZONE"؟

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

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

بافتراض USE_TZ ، يقوم DRF بالفعل بإرجاع أوقات التاريخ بمعلومات المنطقة الزمنية. لذلك فهو يفعل بالفعل ما تحتاجه هناك.

المشكلة الوحيدة هنا هي ما إذا تم تنسيق نفس DT كما هو الحال في منطقة زمنية أو أخرى. (لكنهما ما زالا في نفس الوقت).

تضمين التغريدة

لا يوجد خطأ منطقي هنا.
هذه هي نفس الوقت: "2016-12-19T10: 00: 00 + 5: 30" و "2016-12-19T04: 30: 00Z" - إلى حد ما ، من يهتم بكيفية عودتهم؟

IMHO هذه هي المشكلة: السلسلة التي تم إرجاعها!
أستخدم إعدادات المنطقة الزمنية لـ Django وتعيد جميع القوالب الوقت الصحيح "2016-12-19T10:00:00+5:30" كما توقعنا ، لكن DRF ليس كذلك. إرجاع DRF "2016-12-19T04:30:00Z" .
في العميل ، الذي يستهلك REST apis الخاص بي ، لا يوجد منطق ، ولا يوجد تحويلات أو تفسير لسلسلة التاريخ والوقت.
بعبارة أخرى ، أتوقع أن التاريخ والوقت من استجابة DRF مطابق لـ "استجابة" قالب Django: يقوم الخادم بإعداد جميع البيانات للعميل ويظهرها العميل فقط.

على أي حال ، شكرًا جزيلاً على صبرك ودعمك وعملك الرائع لهذا المشروع الرائع!

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

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

أقبل إذا كنت تستهلك السلسلة الأولية لن تتحقق توقعاتك هنا. (لكن لا تفعل ذلك: تخيل لو أرسلنا الطوابع الزمنية لنظام UNIX ؛ فلا توجد طريقة لاستهلاك تلك الطوابع الأولية. قم بالتحويل إلى كائن تاريخ مناسب ، مهما كان ذلك في لغة العميل.)

أنا سعيد حقًا لأخذ العلاقات العامة في هذا الشأن. (لم أغلقه بعد!)

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

(على هذا النحو ، أنا أميل إلى إغلاقها على أساس أننا سنأخذ العلاقات العامة إذا ظهر أحد)

مرحبًا بالجميع ، يجب إصلاح هذا بواسطة # 5408. إذا كان لديك الوقت لتثبيت الفرع والتحقق من أن كل شيء يعمل كما هو متوقع ، فسيكون ذلك رائعًا. شكرا!

أعتقد أن المشكلة أعيد تقديمها بطريقة ما:

عندما قمت بتغيير TZ الافتراضي من UTC إلى أوروبا / أمستردام ، فشلت إحدى الاختبارات ولاحظت أن DRF يقوم بالتسلسل إلى شيء مختلف عن TZ الافتراضي

تحرير: كانت المشكلة متعلقة باختبار / إعداد المصنع.


إعداد الاختبار أدناه.

نموذج

class Something(StampedModelMixin):
    MIN_VALUE = 1
    MAX_VALUE = 500

    id = models.BigAutoField(primary_key=True)  # pylint: disable=blacklisted-name
    product_id = models.BigIntegerField(db_index=True)
    start_time = models.DateTimeField()
    end_time = models.DateTimeField()
    percentage = models.IntegerField()
    enabled = models.IntegerField()

مصنع

class SomethingFactory(factory.django.DjangoModelFactory):
    """ Base Factory to create records for Something

    """
    start_time = factory.Faker('date_time', tzinfo=get_default_timezone())
    end_time = factory.Faker('date_time', tzinfo=get_default_timezone())
    percentage = factory.Faker('random_int', min=1, max=500)
    enabled = factory.Faker('random_element', elements=[0, 1])

    class Meta:  # pylint: disable=missing-docstring
        model = Something

اختبار الوحدة

class TestSomething:
    def test__get__empty(self):
        # preparation of data
        series = SeriesFactory.create(product_id=2)
        SomethingFactory.create_batch(3, product_id=1)

        # prepare request params
        url = reverse('series-somethings', kwargs={'pk': series.pk})

        # call the endpoint
        response = self.client.get(url)

        # asserts
        assert response.data == []

    def test__get__single(self):
        # preparation of data
        series = SeriesFactory.create(product_id=1)
        old_somethings = SomethingFactory.create_batch(1, product_id=1)

        # prepare request params
        url = reverse('series-somethings', kwargs={'pk': series.pk})

        # call the endpoint
        response = self.client.get(url)

        # asserts
        assert SomethingSerializer(old_somethings, many=True).data == response.data

عرض

class SomethingElseView(APILogMixin, ModelViewSet):
    @action(detail=True, methods=['get'])
    def somethings(self, request, pk=None):
        """ GET endpoint for Somethings

        .. seealso:: :func:`rest_framework.decorators.action`
        """
        otherthings = self.get_object()
        something_qs = Something.objects.all()
        something_qs = something_qs.filter(product_id=otherthings.product_id)
        serializer = self.something_serializer_class(something_qs, many=True)
        return Response(serializer.data)

المسلسل

class SomethingSerializer(serializers.ModelSerializer):

    class Meta:
        model = Something
        list_serializer_class = SomethingListSerializer
        fields = '__all__'
        extra_kwargs = {
            'percentage': {'min_value': Something.MIN_VALUE,
                           'max_value': Something.MAX_VALUE}
        }
        read_only_fields = ('id',
                            'ts_activated',
                            'ts_created',
                            'ts_updated')

اختبار نتيجة ipdb

ipdb> old_somethings
[{'product_id': 1, 'start_time': datetime.datetime(2011, 7, 13, 1, 10, 33, tzinfo=<DstTzInfo 'Europe/Amsterdam' LMT+0:20:00 STD>), 'end_time': datetime.datetime(2003, 3, 10, 9, 31, tzinfo=<DstTzInfo 'Europe/Amsterdam' LMT+0:20:00 STD>), 'percentage': 103, 'enabled': 0}]
ipdb> response.data
[OrderedDict([('id', 1), ('ts_created', '2019-02-27 14:16:33'), ('ts_updated', '2019-02-27 14:16:33'), ('product_id', 1), ('start_time', '2011-07-13 02:50:33'), ('end_time', '2003-03-10 10:11:00'), ('percentage', 103), ('enabled', 0)])]

نتيجة الاختبار

E       AssertionError: assert [OrderedDict(...nabled', 0)])] == [OrderedDict([...nabled', 0)])]
E         At index 0 diff: OrderedDict([('id', 1), ('ts_created', '2019-02-27 14:38:15'), ('ts_updated', '2019-02-27 14:38:15'), ('product_id', 1), ('start_time', '2011-07-13 01:10:33'), ('end_time', '2003-03-10 09:31:00'), ('percentage', 103), ('enabled', 0)]) != OrderedDict([('id', 1), ('ts_created', '2019-02-27 14:38:15'), ('ts_updated', '2019-02-27 14:38:15'), ('product_id', 1), ('start_time', '2011-07-13 02:50:33'), ('end_time', '2003-03-10 10:11:00'), ('percentage', 103), ('enabled', 0)])
E         Full diff:
E         - [OrderedDict([('id', 1), ('ts_created', '2019-02-27 14:38:15'), ('ts_updated', '2019-02-27 14:38:15'), ('product_id', 1), ('start_time', '2011-07-13 01:10:33'), ('end_time', '2003-03-10 09:31:00'), ('percentage', 103), ('enabled', 0)])]
E         ?                                                                                                                                                       ^^^^^^^^^^                          ^^^^^^^^^^^
E         + [OrderedDict([('id', 1), ('ts_created', '2019-02-27 14:38:15'), ('ts_updated', '2019-02-27 14:38:15'), ('product_id', 1), ('start_time', '2011-07-13 02:50:33'), ('end_time', '2003-03-10 10:11:00'), ('percentage', 103), ('enabled', 0)])]
E         ?

كومة:

Django==2.0.10
djangorestframework==3.9.0
factory-boy==2.11.1
Faker==0.8.18
pytz==2018.9

مرحبًا @ diegueus9 - هل يمكنك تقليل هذا إلى حالة اختبار أبسط؟ أنت تقارن البيانات المزيفة المتسلسلة مقابل بيانات استجابة العرض. لذلك ليس من الواضح ما هي القيمة الفعلية المتوقعة. أوصي بمقارنة بعض النتائج بقيمة مضمنة. على سبيل المثال ،

assert SomethingSerializer(old_somethings, many=True).data == {'blah':'blah'}

rpkilby شكرا لإجابتك. لقد كان خطأي ، المشكلة في اختبارات الوحدة الخاصة بي هي أنني كنت أستخدم Factory-boy / faker من أجل ذلك دون التحديث من DB ، ومن هنا كان الاختلاف ، لقد أضفت للتو

    for old_something in old_somethings:
        old_something.refresh_from_db()

هل يجب أن أحذف تعليقي السابق أم يجب أن أتركه في حالة تعرض أي شخص آخر لنفس النتيجة الإيجابية الزائفة؟

مرحبًا @ diegueus9 ، لا تقلق - لقد أخفيت الكود في علامة details .

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