Ticket #12760: tests.py

File tests.py, 6.4 KB (added by defaultwombat, 15 years ago)

Testfile with 2 Models

Line 
1from django.db import models
2from django.contrib.auth.models import User
3
4
5# #
6# THE SETUP
7# #
8
9class Human(models.Model):
10 """A Human MAY have a user assigned"""
11 name = models.CharField(blank=False,null=False,max_length=100)
12 auth_user = models.ForeignKey(User,blank=True,null=True)
13 def __unicode__(self):
14 return self.name
15
16class Joke(models.Model):
17 """a Joke must have owner """
18 text = models.TextField(blank=False,null=False)
19 owner = models.ForeignKey(Human,blank=False,null=False)
20
21# #
22# THE TEST
23# #
24
25from django.test import TestCase
26from django.db.models.query_utils import CollectedObjects
27
28class SimpleTest(TestCase):
29
30 def setUp(self):
31 user = User(username='Authtester',password="secret")
32 user.save()
33
34 human = Human(name='HumanTester',auth_user=user)
35 human.save()
36
37 joke = Joke(text='phunny Joke....',owner=human)
38 joke.save()
39
40 self.user ,self.human,self.joke= user,human,joke
41
42 def test1(self):
43 """
44 The deletion of a User should disconnect it from a Human, but should not delete the Human, neither its Joke)
45 """
46 user, human, joke = self.user, self.human, self.joke
47 user.delete()
48
49 self.assertTrue(len(Human.objects.all()), u'there is no human left')
50 self.assertTrue(len(Joke.objects.all()), u'there is no Joke left')
51
52 def test2(self):
53 """
54 inspecting the objects getting collected by calling delete on a user
55 """
56 user, human, joke = self.user, self.human, self.joke
57
58 seen = CollectedObjects()
59 # calling the collection method used in delete
60 user._collect_sub_objects(seen)
61
62 collected_instances = []
63 for cls,instances in seen.items():
64 collected_instances.extend(instances.values())
65
66 self.assertFalse(joke in collected_instances,u'%s should not get collected because the human.user can be set to "NULL".'%joke)
67 # _collect_sub_objects keeps collection relations and their subrelations
68 # There should be no futher evaluation of sub-relations if a relation can be set to null
69
70 def test3(self):
71 """
72 printing out what happens in the delete_objects funciton
73 """
74 user, human, joke = self.user, self.human, self.joke
75
76 seen = CollectedObjects()
77 user._collect_sub_objects(seen)
78 copy_of_delete_objects(seen)
79
80
81# ############################################################################## #
82# # this is copy of db.models.query.py delete_objects (django version: 1.1.1.)
83# # spiced with some ugly prints to see what happens there
84# ############################################################################## #
85from django.db import connection, transaction
86from django.db.models import signals, sql
87
88def copy_of_delete_objects(seen_objs):
89 print
90 print "."*40
91 print " the delte_object slow-mo"
92 print "."*40
93 """
94 Iterate through a list of seen classes, and remove any instances that are
95 referred to.
96 """
97 if not transaction.is_managed():
98 transaction.enter_transaction_management()
99 forced_managed = True
100 else:
101 forced_managed = False
102 try:
103 ordered_classes = seen_objs.keys()
104 except CyclicDependency:
105 # If there is a cyclic dependency, we cannot in general delete the
106 # objects. However, if an appropriate transaction is set up, or if the
107 # database is lax enough, it will succeed. So for now, we go ahead and
108 # try anyway.
109 ordered_classes = seen_objs.unordered_keys()
110
111 obj_pairs = {}
112 print
113 try:
114 print "1. LOOP over ordered_classes"
115 for cls in ordered_classes:
116 print 'Class: ',cls
117 items = seen_objs[cls].items()
118 items.sort()
119 obj_pairs[cls] = items
120
121 # Pre-notify all instances to be deleted.
122 for pk_val, instance in items:
123 signals.pre_delete.send(sender=cls, instance=instance)
124
125 pk_list = [pk for pk,instance in items]
126 print cls.__name__,"Primarykeys used for delete_batch_related: ",tuple(pk_list)
127 del_query = sql.DeleteQuery(cls, connection)
128 del_query.delete_batch_related(pk_list)
129
130 update_query = sql.UpdateQuery(cls, connection)
131 print cls.__name__, 'UPDATE Queries used'
132 for field, model in cls._meta.get_fields_with_model():
133 if (field.rel and field.null and field.rel.to in seen_objs and
134 filter(lambda f: f.column == field.rel.get_related_field().column,
135 field.rel.to._meta.fields)):
136 if model:
137 sql.UpdateQuery(model, connection).clear_related(field,
138 pk_list)
139 else:
140 update_query.clear_related(field, pk_list)
141
142 print update_query or 'NONE'
143 print
144 print "2. LOOP over ordered_classes"
145 print "# 'ordered_classes' has not been modified. objectes updated previousely are still in that list"
146 # Now delete the actual data.
147 for cls in ordered_classes:
148 print 'Class: ',cls
149 items = obj_pairs[cls]
150 items.reverse()
151
152 pk_list = [pk for pk,instance in items]
153 del_query = sql.DeleteQuery(cls, connection)
154 del_query.delete_batch(pk_list)
155 print ' ',del_query
156 # Last cleanup; set NULLs where there once was a reference to the
157 # object, NULL the primary key of the found objects, and perform
158 # post-notification.
159 for pk_val, instance in items:
160 for field in cls._meta.fields:
161 if field.rel and field.null and field.rel.to in seen_objs:
162 setattr(instance, field.attname, None)
163 print ' ','the object %s gets its %s set to None'%(instance,field.attname)
164
165 signals.post_delete.send(sender=cls, instance=instance)
166 print ' ',"post_delete signal sent"
167 setattr(instance, cls._meta.pk.attname, None)
168 print ' ','the object %s gets its %s set to None'%(instance,cls._meta.pk.attname)
169 if forced_managed:
170 transaction.commit()
171 else:
172 transaction.commit_unless_managed()
173 finally:
174 if forced_managed:
175 transaction.leave_transaction_management()
176 print "."*40
177
Back to Top