1
# -*- encoding: utf-8 -*-
2
from __future__ import unicode_literals
4
from django.core.checks import Error
5
from django.db import models
6
from django.test.utils import override_settings
8
from .base import IsolatedModelsTestCase
11
class IndexTogetherTests(IsolatedModelsTestCase):
13
def test_non_iterable(self):
14
class Model(models.Model):
18
errors = Model.check()
21
"'index_together' must be a list or tuple.",
27
self.assertEqual(errors, expected)
29
def test_non_list(self):
30
class Model(models.Model):
32
index_together = 'not-a-list'
34
errors = Model.check()
37
"'index_together' must be a list or tuple.",
43
self.assertEqual(errors, expected)
45
def test_list_containing_non_iterable(self):
46
class Model(models.Model):
48
index_together = [('a', 'b'), 42]
50
errors = Model.check()
53
"All 'index_together' elements must be lists or tuples.",
59
self.assertEqual(errors, expected)
61
def test_pointing_to_missing_field(self):
62
class Model(models.Model):
68
errors = Model.check()
71
"'index_together' refers to the non-existent field 'missing_field'.",
77
self.assertEqual(errors, expected)
79
def test_pointing_to_m2m_field(self):
80
class Model(models.Model):
81
m2m = models.ManyToManyField('self')
88
errors = Model.check()
91
("'index_together' refers to a ManyToManyField 'm2m', but "
92
"ManyToManyFields are not permitted in 'index_together'."),
98
self.assertEqual(errors, expected)
101
# unique_together tests are very similar to index_together tests.
102
class UniqueTogetherTests(IsolatedModelsTestCase):
104
def test_non_iterable(self):
105
class Model(models.Model):
109
errors = Model.check()
112
"'unique_together' must be a list or tuple.",
118
self.assertEqual(errors, expected)
120
def test_list_containing_non_iterable(self):
121
class Model(models.Model):
122
one = models.IntegerField()
123
two = models.IntegerField()
126
unique_together = [('a', 'b'), 42]
128
errors = Model.check()
131
"All 'unique_together' elements must be lists or tuples.",
137
self.assertEqual(errors, expected)
139
def test_non_list(self):
140
class Model(models.Model):
142
unique_together = 'not-a-list'
144
errors = Model.check()
147
"'unique_together' must be a list or tuple.",
153
self.assertEqual(errors, expected)
155
def test_valid_model(self):
156
class Model(models.Model):
157
one = models.IntegerField()
158
two = models.IntegerField()
161
# unique_together can be a simple tuple
162
unique_together = ('one', 'two')
164
errors = Model.check()
165
self.assertEqual(errors, [])
167
def test_pointing_to_missing_field(self):
168
class Model(models.Model):
174
errors = Model.check()
177
"'unique_together' refers to the non-existent field 'missing_field'.",
183
self.assertEqual(errors, expected)
185
def test_pointing_to_m2m(self):
186
class Model(models.Model):
187
m2m = models.ManyToManyField('self')
194
errors = Model.check()
197
("'unique_together' refers to a ManyToManyField 'm2m', but "
198
"ManyToManyFields are not permitted in 'unique_together'."),
204
self.assertEqual(errors, expected)
207
class FieldNamesTests(IsolatedModelsTestCase):
209
def test_ending_with_underscore(self):
210
class Model(models.Model):
211
field_ = models.CharField(max_length=10)
212
m2m_ = models.ManyToManyField('self')
214
errors = Model.check()
217
'Field names must not end with an underscore.',
219
obj=Model._meta.get_field('field_'),
223
'Field names must not end with an underscore.',
225
obj=Model._meta.get_field('m2m_'),
229
self.assertEqual(errors, expected)
231
def test_including_separator(self):
232
class Model(models.Model):
233
some__field = models.IntegerField()
235
errors = Model.check()
238
'Field names must not contain "__".',
240
obj=Model._meta.get_field('some__field'),
244
self.assertEqual(errors, expected)
247
class Model(models.Model):
248
pk = models.IntegerField()
250
errors = Model.check()
253
"'pk' is a reserved word that cannot be used as a field name.",
255
obj=Model._meta.get_field('pk'),
259
self.assertEqual(errors, expected)
262
class ShadowingFieldsTests(IsolatedModelsTestCase):
264
def test_multiinheritance_clash(self):
265
class Mother(models.Model):
266
clash = models.IntegerField()
268
class Father(models.Model):
269
clash = models.IntegerField()
271
class Child(Mother, Father):
272
# Here we have two clashed: id (automatic field) and clash, because
273
# both parents define these fields.
276
errors = Child.check()
279
("The field 'id' from parent model "
280
"'invalid_models_tests.mother' clashes with the field 'id' "
281
"from parent model 'invalid_models_tests.father'."),
287
("The field 'clash' from parent model "
288
"'invalid_models_tests.mother' clashes with the field 'clash' "
289
"from parent model 'invalid_models_tests.father'."),
295
self.assertEqual(errors, expected)
297
def test_inheritance_clash(self):
298
class Parent(models.Model):
299
f_id = models.IntegerField()
301
class Target(models.Model):
302
# This field doesn't result in a clash.
303
f_id = models.IntegerField()
306
# This field clashes with parent "f_id" field.
307
f = models.ForeignKey(Target)
309
errors = Child.check()
312
("The field 'f' clashes with the field 'f_id' "
313
"from model 'invalid_models_tests.parent'."),
315
obj=Child._meta.get_field('f'),
319
self.assertEqual(errors, expected)
321
def test_id_clash(self):
322
class Target(models.Model):
325
class Model(models.Model):
326
fk = models.ForeignKey(Target)
327
fk_id = models.IntegerField()
329
errors = Model.check()
332
("The field 'fk_id' clashes with the field 'fk' from model "
333
"'invalid_models_tests.model'."),
335
obj=Model._meta.get_field('fk_id'),
339
self.assertEqual(errors, expected)
342
class OtherModelTests(IsolatedModelsTestCase):
344
def test_unique_primary_key(self):
345
invalid_id = models.IntegerField(primary_key=False)
347
class Model(models.Model):
350
errors = Model.check()
353
"'id' can only be used as a field name if the field also sets 'primary_key=True'.",
359
self.assertEqual(errors, expected)
361
def test_ordering_non_iterable(self):
362
class Model(models.Model):
364
ordering = "missing_field"
366
errors = Model.check()
369
("'ordering' must be a tuple or list "
370
"(even if you want to order by only one field)."),
376
self.assertEqual(errors, expected)
378
def test_non_valid(self):
379
class RelationModel(models.Model):
382
class Model(models.Model):
383
relation = models.ManyToManyField(RelationModel)
386
ordering = ['relation']
388
errors = Model.check()
391
"'ordering' refers to the non-existent field 'relation'.",
397
self.assertEqual(errors, expected)
399
def test_ordering_pointing_to_missing_field(self):
400
class Model(models.Model):
402
ordering = ("missing_field",)
404
errors = Model.check()
407
"'ordering' refers to the non-existent field 'missing_field'.",
413
self.assertEqual(errors, expected)
415
def test_ordering_pointing_to_missing_foreignkey_field(self):
418
class Model(models.Model):
419
missing_fk_field = models.IntegerField()
422
ordering = ("missing_fk_field_id",)
424
errors = Model.check()
427
"'ordering' refers to the non-existent field 'missing_fk_field_id'.",
433
self.assertEqual(errors, expected)
435
def test_ordering_pointing_to_existing_foreignkey_field(self):
438
class Parent(models.Model):
441
class Child(models.Model):
442
parent = models.ForeignKey(Parent)
445
ordering = ("parent_id",)
447
self.assertFalse(Child.check())
449
@override_settings(TEST_SWAPPED_MODEL_BAD_VALUE='not-a-model')
450
def test_swappable_missing_app_name(self):
451
class Model(models.Model):
453
swappable = 'TEST_SWAPPED_MODEL_BAD_VALUE'
455
errors = Model.check()
458
"'TEST_SWAPPED_MODEL_BAD_VALUE' is not of the form 'app_label.app_name'.",
464
self.assertEqual(errors, expected)
466
@override_settings(TEST_SWAPPED_MODEL_BAD_MODEL='not_an_app.Target')
467
def test_swappable_missing_app(self):
468
class Model(models.Model):
470
swappable = 'TEST_SWAPPED_MODEL_BAD_MODEL'
472
errors = Model.check()
475
("'TEST_SWAPPED_MODEL_BAD_MODEL' references 'not_an_app.Target', "
476
'which has not been installed, or is abstract.'),
482
self.assertEqual(errors, expected)
484
def test_two_m2m_through_same_relationship(self):
485
class Person(models.Model):
488
class Group(models.Model):
489
primary = models.ManyToManyField(Person,
490
through="Membership", related_name="primary")
491
secondary = models.ManyToManyField(Person, through="Membership",
492
related_name="secondary")
494
class Membership(models.Model):
495
person = models.ForeignKey(Person)
496
group = models.ForeignKey(Group)
498
errors = Group.check()
501
("The model has two many-to-many relations through "
502
"the intermediate model 'invalid_models_tests.Membership'."),
508
self.assertEqual(errors, expected)