Django-rest-framework: Serializer DateTimeField enthält unerwartete Zeitzoneninformationen

Erstellt am 13. Dez. 2015  ·  34Kommentare  ·  Quelle: encode/django-rest-framework

Ich habe TIME_ZONE = 'Asia/Kolkata' und USE_TZ = True in meinen Einstellungen.

Wenn ich ein neues Objekt mit der durchsuchbaren API erstelle, zeigt der Serializer das neu erstellte Objekt mit Datumsangaben an, die ein nachgestelltes +5:30 , was die Zeitzone angibt. Die Datenbank speichert die Zeiten in UTC.

Das unerwartete Verhalten ist, dass, wenn das Objekt später erneut serialisiert wird, die Datumsangaben alle im UTC-Format mit einem abschließenden Z vorliegen. Gemäß den Django-Dokumenten zur aktuellen und Standardzeitzone würde ich erwarten, dass der Serializer die Datetimes in die aktuelle Zeitzone konvertiert, die standardmäßig auf die Standardzeitzone eingestellt ist, die durch TIME_ZONE = 'Asia/Kolkata' .

Verpasse ich etwas?

Needs further review

Hilfreichster Kommentar

Würde mich auch über diese Funktion freuen. Ich bin der Meinung, dass die Einstellung USE_TZ respektiert und die Werte konvertiert werden sollten, ähnlich dem Standardverhalten von Django.

Alle 34 Kommentare

Ich habe nach Stack-Überlauf gefragt und die Schlussfolgerung ist, dass die aktuelle Zeitzone nur für vom Benutzer bereitgestellte Datumsangaben verwendet wird, da die Datumszeit nach der Validierung (dh nach dem Erstellen oder Aktualisieren) unverändert serialisiert wird. Aus der Django-Dokumentation finde ich es schwer zu glauben, dass dies beabsichtigt ist, aber dies ist ein Problem mit Django selbst und nicht mit dem Rest Framework, daher werde ich dieses Problem schließen.

Hallo @tomchristie ,

Ich denke, das ist ein DRF-Fehler.
IMHO, die natürliche Verwendung von DRF besteht darin, es als Ausgabe wie eine Django-Vorlage zu verwenden.
In einer Django-Vorlage wird die Zeitzone korrekt angezeigt, warum respektiert der drf-Serializer die Django-Zeitzoneneinstellung nicht?

Hi,

Wenn ich mir den Code in fields.py in der Klasse DatetimeField ansehe, entdecke ich, dass die Django-Zeitzoneneinstellung nur für den internen Wert ( to_internal_value() ) gut berücksichtigt wird.

Ich habe gesehen, dass mit dem Modell Serializer wie folgt:

class MyModelSerializer(ModelSerializer):

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

für das Feld my_date_time_field (das ich denke, es ist ein DateTimeField :) ) ist die Zeitzone für die Darstellung standardmäßig None ( to_representation() ).

Mit anderen Worten, wenn ich mich nicht irre, wird die Django-Zeitzone nur berücksichtigt, wenn der Wert in das Speicher-Backend geschrieben wird.

IMHO denke ich, dass der Rückgabewert von to_representation() so aussehen sollte:
return self.enforce_timezone(value).strftime(output_format)
entsprechend der Einstellung Django USE_TZ .

Dazu schreibe ich einen Pull-Request.

Ciao
Valentino

@vpistis Es wäre einfacher, dies zu überprüfen, wenn Sie ein Beispiel für das API-Verhalten geben könnten, das Sie derzeit sehen, und was Sie erwarten würden (anstatt zuerst die Implementierungsaspekte zu diskutieren).

Legen Sie TIME_ZONE = 'Asia/Kolkata' und erstellen Sie einen Modellserializer mit einem einzigen Datums-/Uhrzeitfeld, appointment .

Senden Sie während der Erstellung/Aktualisierung:

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

und zurück:

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

Aber wenn Sie dieses Objekt erneut abrufen oder auflisten, erhalten Sie:

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

Wenn bei der Erstellung kein Z angegeben ist, geht DRF davon aus, dass der Client die durch TIME_ZONE angegebene Zeitzone verwendet und gibt eine in dieser Zeitzone formatierte Zeit zurück (durch Hinzufügen von +5:30 am Ende, was wäre tatsächlich ungültig, wenn es sich um eine vom Kunden bereitgestellte Zeit handelt). Es wäre wahrscheinlich sinnvoller, wenn zukünftige Zugriffe auch eine in dieser Zeitzone formatierte Zeit zurückliefern, sodass die Antwort beim Abrufen/Listen die gleiche wäre wie beim Erstellen/Aktualisieren.

Es stellt sich auch die Frage, ob Zeiten in der konfigurierten Zeitzone zurückgegeben werden sollen, wenn das nachgestellte Z bei der Erstellung/Aktualisierung bereitgestellt wird, so dass gesendet wird:

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

kehrt zurück:

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

Ich wäre dafür, da es die Antwort mit der Antwort für Listen/Abrufe konsistent hält.

Eine andere Möglichkeit wäre, immer UTC-Zeiten zurückzugeben, auch während der Erstellung/Aktualisierung, aber das finde ich weniger nützlich. In jedem Fall wären konsistente Zeitzonen der 50/50-Situation, die wir derzeit haben, vorzuziehen.

Legen Sie Ihre TIME_ZONE = 'Asia/Kolkata' fest und erstellen Sie einen Modell-Serializer mit einem einzigen Datums-/Uhrzeitfeld, Termin.

Senden Sie während der Erstellung/Aktualisierung:

{
"Termin": "2016-12-19T10:00:00"
}
und zurück:

{
"Termin": "2016-12-19T10:00:00+5:30"
}
Aber wenn Sie dieses Objekt erneut abrufen oder auflisten, erhalten Sie:

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

danke @jonathan-golorry Dies ist genau das Verhalten, das ich tatsächlich sehe.
Für mich sollte das Verhalten so sein (mit @jonathan-golorry Beispiel :) ):

Senden Sie beim Erstellen/Aktualisieren mit dem Standard-DATETIME_FORMAT:

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

und zurück:

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

Wenn Sie dieses Objekt erneut abrufen oder auflisten, erhalten Sie:

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

IMHO sollte vielleicht eine DRF-Einstellung sein, um dieses Verhalten zu verwalten, zum Beispiel eine Einstellung, die erzwingt, dass das DateTimeField mit der Standardzeitzone dargestellt wird.

vielen Dank @tomchristie

Die Inkonsistenz zwischen unterschiedlichen Aktionen ist hier der Ausschlag für die Wiedereröffnung. Ich hatte nicht bemerkt, dass das der Fall war. Ich würde erwarten, dass wir standardmäßig UTC verwenden, obwohl wir dies optional machen

Für eine Produktionswebanwendung, die DRF 3.4.6 verwendet, haben wir diese Problemumgehung gelöst:
https://github.com/vpistis/django-rest-framework/commit/be62db9080b19998d4de3a1f651a291d691718f6

Wenn jemand einen Pull-Request senden möchte, der entweder Folgendes enthält:

  • nur fehlgeschlagene Testfälle enthält, oder ...
  • Testfall + Fix

das wäre sehr willkommen.

Ich habe Code zum Testen geschrieben, bin mir aber nicht sicher, wie DRF-Testfälle verwendet werden. Ich weiß nicht, wie man Django-Einstellungen verwalten kann, um die Zeitzone und andere Einstellungen zur Laufzeit zu ändern.
Bitte verlinken Sie mir ein konkretes Beispiel oder eine Anleitung.

danke

Wenn Sie die globalen Testeinstellungen ändern möchten, finden Sie sie hier .

Wenn Sie versuchen, die Einstellungen während des Tests zu überschreiben, können Sie den override_settings Dekorator verwenden .

Würde mich auch über diese Funktion freuen. Ich bin der Meinung, dass die Einstellung USE_TZ respektiert und die Werte konvertiert werden sollten, ähnlich dem Standardverhalten von Django.

Der erste Schritt hier wäre, einen fehlgeschlagenen Testfall zu schreiben, den wir der aktuellen Testsuite hinzufügen können.
Der nächste Schritt wäre, einen Fix für diesen Fall zu starten :)

Hi,
für mich ist dies ein Testfall für diese Funktion

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()

In meinem Fork benutze ich irgendeinen Trick um mal in die richtige Zeitzone meine 3.6.2_tz_fix zu bekommen .

Ich hoffe das hilft :)

Ich sehe, dass dies geschlossen ist, aber ich verwende drf 3.6.3 und in meiner Postgres-Datenbank habe ich diesen Zeitstempel "2017-07-12 14:26:00-06", aber wenn ich die Daten mit Postman erhalte, erhalte ich diesen "Zeitstempel" : "2017-07-12T20:26:00Z". Ich sehe aus, als würde es die -06 Stunden hinzufügen.

Meine Django-Einstellungen verwenden tzlocal, um die Zeitzone TIME_ZONE = str(get_localzone()) einzustellen. Die Zeitzone wird also beim Start eingestellt.

Ich verwende ein BasismodellSerializer

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

Verpasse ich etwas?

nicht geschlossen, es ist noch offen :)
Der rote "geschlossene Button", den Sie sehen, ist für das Referenzproblem.
...und du hast recht, der "Bug" ist immer noch da ;(
Der Meilenstein wird von 3.6.3 in 3.6.4 geändert.

Oh, ok. Dankeschön!

Am 12. Juli 2017 17:10, "Valentino Pistis" [email protected]
schrieb:

nicht geschlossen, es ist noch offen :)
Der rote "geschlossene Button", den Sie sehen, ist für das Referenzproblem.
...und du hast recht, der "Bug" ist immer noch da ;(
Der Meilenstein wird von 3.6.3 in 3.6.4 geändert.


Sie erhalten dies, weil Sie einen Kommentar abgegeben haben.
Antworten Sie direkt auf diese E-Mail und zeigen Sie sie auf GitHub an
https://github.com/encode/django-rest-framework/issues/3732#issuecomment-314923582 ,
oder den Thread stumm schalten
https://github.com/notifications/unsubscribe-auth/AIMBTcx-6PPbi_SOqeLCjeWV1Rb59-Ohks5sNVJ0gaJpZM4G0aRE
.

Hi,

Ich bin mir nicht sicher, ob dies vollständig mit der ursprünglichen Frage zusammenhängt, aber sollte DRF alle Zeitzonenüberschreibungen berücksichtigen, die gemäß https://docs.djangoproject.com/en/1.11/ref/utils/#django festgelegt sind. utils.timezone.activate ?

Ich habe ein System, in dem meine Benutzer einer Zeitzone zugeordnet sind und die API naive Datumsangaben empfängt. Ich erwarte, dass ich diese Datumsangaben in die Zeitzone des aktuellen Benutzers konvertieren kann, aber ich stelle fest, dass ../rest_framework/fields.py die Standardzeitzone anwendet (dh die aus der Django-Einstellungsdatei:

    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

Sollte dies wirklich timezone.get_current_timezone() als Voreinstellung verwenden, falls die Anwendung eine Überschreibung festgelegt hat, wie in meinem Fall?

Hallo @RichardForshaw , das scheint ein eigenes Problem zu sein, aber sicherlich das gleiche

Wenn wir eine anständige Reihe von Testfällen erhalten, die das erwartete Verhalten abdecken, würden wir uns hier sicherlich eine PR ansehen.

Mein erster Gedanke ist darüber hinaus, sicherzustellen, dass Sie die Zeitzoneninformationen an die API senden, anstatt sich auf die konfigurierte Zeitzone des Servers zu verlassen. Darüber hinaus bin ich auch der Meinung, dass Sie bereit sein müssen, eine Zeit auf dem Client zu lokalisieren.

Aber ja, hier gibt es eine Inkonsistenz, die behoben werden muss. (Habe ich PRs Willkommen erwähnt? 🙂)

carltongibson/django-filter#750 sollte hier relevant sein. Ich habe die Zeitzonenbehandlung von django-filter ursprünglich auf DRF basiert, so dass die Änderungen in 750 hier leicht angewendet werden konnten.

Entschuldigung für meinen Neuling, aber was genau ist hier das Problem? Der Zeitstempel in meiner psql-Datenbank ist korrekt und Django verwendet die richtige Zeitzone. Gibt es DRF-Einstellungen, damit keine Zeitstempel konvertiert werden?

Hallo @michaelaelise — wenn du dir das Beispiel der Daten (ganz oben)

  1. Sie senden eine Datumszeit ohne Zeitzoneninformationen. (Dies ist ein schlechter Zug in meinem Buch.)
  2. Der Server wendet seine lokale Zeitzone an und kommt als diese zurück (in diesem Fall +5:30 )
  3. Aber später, wenn Sie es abrufen, wird es als UTC zurückgegeben ( Z , für "Zulu", nehme ich an).

Die Annahme, dass Ihr Client die Zeitzonenkonvertierung für Sie übernimmt, ist kein Problem. (Außer vielleicht Nr. 1, denn wer sagt, dass Ihr Client die gleiche Zeitzoneneinstellung wie Ihr Server hat...?)

Aber es ist eine kleine Inkonsistenz, 2 und 3 sollten doch das gleiche Format haben? (Auch wenn ein Client korrekterweise beide als äquivalente Werte akzeptiert.)

Ich neige dazu, dies zu schließen.

  • Hier liegt kein Logikfehler vor.

    • Dies sind gleichzeitig: "2016-12-19T10:00:00+5:30" und "2016-12-19T04:30:00Z" – bis zu einem gewissen Grad, wen interessiert es, wie sie zurückkommen?

  • Daher kann ich es nicht rechtfertigen, wirklich Zeit zu investieren.
  • Das Ticket ist 2 Jahre alt und niemand hat eine PR angeboten.

Ich schaue mir gerne eine PR an, aber ich bin mir nicht sicher, ob ich dies wirklich als _offenes Thema_ betrachten möchte.

Oh, mir war in meinem ursprünglichen Beitrag in diesem Thementhread nicht klar, dass das "Z" das bedeutet.
DRF konvertiert also die bekannte Datumszeit in UTC, damit sie von der Benutzeroberfläche/dem Anrufer verarbeitet wird?
Vielen Dank für diese Klarstellung.

Eine letzte Sache.
Was ist, wenn wir möchten, dass "2016-12-19T10:00:00+5:30" zurückgegeben wird, weil wir Geräte in verschiedenen Zeitzonen abfragen.
Könnte dies eine Einstellung "RETURN_DATETIME_WITH_TIMEZONE" sein?

Wir verwenden django/drf auf Edge-Geräten. Daher ist es für alle eingefügten Datumsangaben egal, ob es naiv ist oder nicht, da die Zeitzone des Edge-Geräts konfiguriert ist und das Postgres-Feld immer für die Datumszeit des Geräts genau ist.

Der Cloud-Server im aktuellen Szenario müsste dann die Zeitzone jedes Geräts kennen, wahrscheinlich wird dies nur die Arbeit von django/drf in die Cloud-App verlagern.

Unter der Annahme von USE_TZ gibt DRF bereits Datumsangaben mit den Zeitzoneninformationen zurück. Es tut also bereits das, was Sie dort brauchen.

Das einzige Problem hierbei ist, ob das gleiche DT wie in der einen oder anderen Zeitzone formatiert ist. (Aber sie sind immer noch die gleiche Zeit.)

@carltongibson

Hier liegt kein Logikfehler vor.
Dies sind die gleichen Uhrzeiten: "2016-12-19T10:00:00+5:30" und "2016-12-19T04:30:00Z" — bis zu einem gewissen Grad, wen interessiert es, wie sie zurückkommen?

IMHO ist das das Problem: der zurückgegebene String!
Ich verwende Django-Zeitzoneneinstellungen und alle Vorlagen geben die richtige Zeit "2016-12-19T10:00:00+5:30" wie erwartet zurück, DRF jedoch nicht. DRF gibt "2016-12-19T04:30:00Z" .
In den Client, der meine REST-Apis konsumiert, gibt es keine Logik, keine Zeitkonvertierungen oder Datetime-String-Interpretation.
Mit anderen Worten, ich erwarte, dass die Datumszeit einer DRF-Antwort identisch mit der "Antwort" des Django-Templates ist: Der Server bereitet alle Daten für den Client vor und der Client zeigt sie nur an.

Wie auch immer, vielen Dank für Ihre Geduld, Unterstützung und Ihre großartige Arbeit für dieses fantastische Projekt!

@vpistis mein Punkt hier ist nur, dass das dargestellte Datum korrekt ist, nur die Darstellung wird nicht erwartet. Sobald Sie das auf ein natives Datum parsen, gibt es keinen Unterschied, wie auch immer Ihre Sprache dies handhabt.

Ich würde erwarten, dass Benutzer die Datumszeichenfolge in ein Datum parsen, aber ihre Clientsprache sieht dies vor, anstatt die Rohzeichenfolge zu verbrauchen.

Ich akzeptiere, wenn Sie die rohe Saite konsumieren, werden Ihre Erwartungen hier nicht erfüllt. (Aber tun Sie das nicht: Stellen Sie sich vor, wir würden UNIX-Zeitstempel senden; Sie würden diese auf keinen Fall roh konsumieren. Konvertieren Sie in ein richtiges Date-Objekt, was auch immer in Ihrer Clientsprache ist.)

Ich freue mich sehr über eine PR dazu. (Ich habe es noch nicht geschlossen!)

Aber seit der Meldung sind fast zwei Jahre vergangen und seit dem ersten Kommentar (Ihrer, ein Jahr später) sind es neun Monate. Niemand hat uns auch nur einen fehlgeschlagenen Testfall gegeben. Es kann für niemanden so wichtig sein. Daher ist es schwierig, ihm Zeit zuzuordnen.

(Deshalb neige ich dazu, es zu schließen, weil wir eine PR machen, wenn einer jemals auftaucht)

Hallo zusammen, dies sollte von #5408 behoben werden. Wenn Sie die Zeit haben, den Zweig zu installieren und zu überprüfen, ob alles wie erwartet funktioniert, wäre das fantastisch. Vielen Dank!

Ich denke, das Problem wurde irgendwie wieder eingeführt:

Als ich die Standard-TZ von UTC in Europa/Amsterdam geändert habe, ist einer der Tests fehlgeschlagen und ich habe festgestellt, dass DRF auf etwas anderes als die Standard-TZ serialisiert wird

Bearbeiten: Das Problem bezog sich auf die Test-/Werkskonfiguration.


Testaufbau unten.

Modell

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()

Fabrik

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

Gerätetest

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

Aussicht

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)

Serialisierer

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-Ergebnis testen

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)])]

Testergebnis

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         ?

Stapel:

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

Hallo @diegueus9 - könnten Sie dies auf einen einfacheren Testfall reduzieren? Sie vergleichen serialisierte gefälschte Daten mit den Antwortdaten einer Ansicht. Es ist also nicht klar, was der tatsächliche Erwartungswert ist. Ich würde empfehlen, ein Ergebnis mit einem hartcodierten Wert zu vergleichen. z.B,

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

@rpkilby danke für deine Antwort. Es war mein Fehler, das Problem mit meinen Unit-Tests ist, dass ich dafür Factory-Boy / Faker verwendet habe, ohne von DB zu aktualisieren, daher der Unterschied, den ich gerade hinzugefügt habe

    for old_something in old_somethings:
        old_something.refresh_from_db()

Sollte ich meinen vorherigen Kommentar entfernen oder sollte ich ihn verlassen, falls jemand anderes dasselbe falsch positive Ergebnis erlebt?

Hallo @diegueus9 , keine Sorge - ich habe den Code gerade in einem details Tag versteckt.

War diese Seite hilfreich?
0 / 5 - 0 Bewertungen