@ Crast Antwort tun konnte, war, aber ich denke, unvollständig. Der Code, den ich in meiner Einheit verwende, um festzustellen, ob ein Objekt in der Datenbank ist, ist wie folgt. Darunter werde ich erklären, warum ich denke, es ist besser als zu überprüfen, ob obj.pk is None
.
Meine Lösung
from django.test import TestCase
class TestCase(TestCase):
def assertInDB(self, obj, msg=None):
"""Test for obj's presence in the database."""
fullmsg = "Object %r unexpectedly not found in the database" % obj
fullmsg += ": " + msg if msg else ""
try:
type(obj).objects.get(pk=obj.pk)
except obj.DoesNotExist:
self.fail(fullmsg)
def assertNotInDB(self, obj, msg=None):
"""Test for obj's absence from the database."""
fullmsg = "Object %r unexpectedly found in the database" % obj
fullmsg += ": " + msg if msg else ""
try:
type(obj).objects.get(pk=obj.pk)
except obj.DoesNotExist:
return
else:
self.fail(fullmsg)
Hinweise: den obigen Code mit Vorsicht walten lassen, wenn Sie benutzerdefinierte Manager auf Ihrem Modelle Name etwas anderes als objects
verwenden. (Ich bin sicher, es gibt eine Möglichkeit, Django dazu zu bringen, Ihnen zu sagen, was der Standardmanager ist.) Außerdem weiß ich, dass /assert(Not)?InDB/
keine PEP 8-Methodennamen sind, aber ich habe den Stil des restlichen unittest
Pakets verwendet.
Begründung
Der Grund, warum ich denke, assertInDB(obj)
als assertIsNotNone(obj.pk)
besser ist, weil der folgende Fall. Angenommen, Sie haben das folgende Modell.
from django.db import models
class Node(models.Model):
next = models.OneToOneField('self', null=True, related_name='prev')
Node
Modelle eine doppelt verknüpfte Liste: Sie beliebige Daten an jeden Knoten mit Fremdschlüssel anbringen kann und der Schwanz ist die Node
obj so dass obj.next is None
. Standardmäßig fügt Django die SQL-Einschränkung ON DELETE CASCADE
dem Primärschlüssel Node
hinzu. Nun nehme an, Sie haben eine list
Knoten der Länge n so dass nodes[i].next == nodes[i + 1]
für i in [0, n-1). Angenommen, Sie rufen nodes[0].delete()
. In meinen Tests auf Django 1.5.1 auf Python 3.3 fand ich, dass nodes[i].pk is not None
für i in [1, n) und nur nodes[0].pk is None
. Jedoch haben meine obigen /assert(Not)?InDB/
Methoden korrekt erkannt, dass nodes[i]
für i in [1, n] tatsächlich gelöscht worden war.
Es gibt standardmäßig einen booleschen kwarg 'created' im Post-Speichern-Signal, so dass Sie keine eigenen einfügen müssen. – kibitzer
Für modernes Django sollte beachtet werden, dass dies nicht funktioniert, wenn Sie Ihre eigenen Primärschlüsselfelder mit einem Standardwertgenerator wie einem UUIDField oder einer anderen Methode zum Generieren von IDs verwenden. Wie in anderen Antworten erwähnt, sollten Sie 'self._state.adding' verwenden. https://stackoverflow.com/a/19379636/23972 –