我想對 Django 模型欄位進行單元測驗:
class Animal(models.Model):
name = models.CharField(unique=True, max_length=30, blank=False, null=False)
class Meta:
managed = True
db_table = 'animal'
ordering = ['name']
我的測驗設定如下所示:
class TestAnimalModel(TestCase):
def setUp(self):
self.animal = Animal.objects.create(name = 'TestAnimal')
self.animal2 = Animal.objects.create(name = 123)
self.animal3 = Animal.objects.create(name = 'TestAnimalWithTooManyCharacters')
動物 2 和動物 3 即使它們不應該被創建,因為動物 2.name 是 int 并且動物 3.name 有超過 30 個字符。
那么如何測驗 name 欄位是否具有正確的值?
即使物件具有與模型不匹配的值,它也被創建是否正常?
uj5u.com熱心網友回復:
他們不應該因為
animal2.name是int
ACharField將呼叫str(…)作為值傳遞的內容。這有時會產生意想不到的副作用。但是 Django 欄位被設計為接受各種值。例如,對于 a DateField,它還接受格式為 的日期YYYY-MM-DD。我們可以在[GitHub]的實作中CharField看到這一點:
class CharField(Field): # … def to_python(self, value): """Return a string.""" if value not in self.empty_values: value = str(value) if self.strip: value = value.strip() if value in self.empty_values: return self.empty_value return value
animal3.name有30多個字符。
如果我用 MySQL 運行它,我會得到一個:
>>> Animal.objects.create(name='TestAnimalWithTooManyCharacters')
Traceback (most recent call last):
File "/django/env/lib/python3.8/site-packages/django/db/backends/utils.py", line 84, in _execute
return self.cursor.execute(sql, params)
File "/django/env/lib/python3.8/site-packages/django/db/backends/mysql/base.py", line 73, in execute
return self.cursor.execute(query, args)
File "/django/env/lib/python3.8/site-packages/MySQLdb/cursors.py", line 206, in execute
res = self._query(query)
File "/django/env/lib/python3.8/site-packages/MySQLdb/cursors.py", line 319, in _query
db.query(q)
File "/django/env/lib/python3.8/site-packages/MySQLdb/connections.py", line 259, in query
_mysql.connection.query(self, query)
MySQLdb._exceptions.DataError: (1406, "Data too long for column 'name' at row 1")
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "<console>", line 1, in <module>
File "/django/env/lib/python3.8/site-packages/django/db/models/manager.py", line 85, in manager_method
return getattr(self.get_queryset(), name)(*args, **kwargs)
File "/django/env/lib/python3.8/site-packages/django/db/models/query.py", line 453, in create
obj.save(force_insert=True, using=self.db)
File "/django/env/lib/python3.8/site-packages/django/db/models/base.py", line 726, in save
self.save_base(using=using, force_insert=force_insert,
File "/django/env/lib/python3.8/site-packages/django/db/models/base.py", line 763, in save_base
updated = self._save_table(
File "/django/env/lib/python3.8/site-packages/django/db/models/base.py", line 868, in _save_table
results = self._do_insert(cls._base_manager, using, fields, returning_fields, raw)
File "/django/env/lib/python3.8/site-packages/django/db/models/base.py", line 906, in _do_insert
return manager._insert(
File "/django/env/lib/python3.8/site-packages/django/db/models/manager.py", line 85, in manager_method
return getattr(self.get_queryset(), name)(*args, **kwargs)
File "/django/env/lib/python3.8/site-packages/django/db/models/query.py", line 1270, in _insert
return query.get_compiler(using=using).execute_sql(returning_fields)
File "/django/env/lib/python3.8/site-packages/django/db/models/sql/compiler.py", line 1410, in execute_sql
cursor.execute(sql, params)
File "/django/env/lib/python3.8/site-packages/django/db/backends/utils.py", line 98, in execute
return super().execute(sql, params)
File "/django/env/lib/python3.8/site-packages/django/db/backends/utils.py", line 66, in execute
return self._execute_with_wrappers(sql, params, many=False, executor=self._execute)
File "/django/env/lib/python3.8/site-packages/django/db/backends/utils.py", line 75, in _execute_with_wrappers
return executor(sql, params, many, context)
File "/django/env/lib/python3.8/site-packages/django/db/backends/utils.py", line 84, in _execute
return self.cursor.execute(sql, params)
File "/django/env/lib/python3.8/site-packages/django/db/utils.py", line 90, in __exit__
raise dj_exc_value.with_traceback(traceback) from exc_value
File "/django/env/lib/python3.8/site-packages/django/db/backends/utils.py", line 84, in _execute
return self.cursor.execute(sql, params)
File "/django/env/lib/python3.8/site-packages/django/db/backends/mysql/base.py", line 73, in execute
return self.cursor.execute(query, args)
File "/django/env/lib/python3.8/site-packages/MySQLdb/cursors.py", line 206, in execute
res = self._query(query)
File "/django/env/lib/python3.8/site-packages/MySQLdb/cursors.py", line 319, in _query
db.query(q)
File "/django/env/lib/python3.8/site-packages/MySQLdb/connections.py", line 259, in query
_mysql.connection.query(self, query)
django.db.utils.DataError: (1406, "Data too long for column 'name' at row 1")
根據您使用的資料庫,它可能(不)被接受。例如,SQLite不強制執行長度限制。的確,作為FAQ的SQLite的說:
(9) SQLite 中 VARCHAR 的最大大小是多少?
SQLite does not enforce the length of a
VARCHAR. You can declare aVARCHAR(10)and SQLite will be happy to store a 500-million character string there. And it will keep all 500-million characters intact. Your content is never truncated. SQLite understands the column type of "VARCHAR(N)" to be the same as "TEXT", regardless of the value ofN.
So SQLite will not validate it.
You can let the Django validators run however before saving it to the database, for example with:
animal = Animal(name='TestAnimalWithTooManyCharacters')
animal.full_clean()
animal.save()
This will let the Django validators run and raise exceptions if the data is not valid:
>>> animal = Animal(name='TestAnimalWithTooManyCharacters')
>>> animal.full_clean()
Traceback (most recent call last):
File "<console>", line 1, in <module>
File "/django/env/lib/python3.8/site-packages/django/db/models/base.py", line 1238, in full_clean
raise ValidationError(errors)
django.core.exceptions.ValidationError: {'name': ['Ensure this value has at most 30 characters (it has 31).']}
A Django ModelForm will also check this and reject the data passed to the form in case the string is too long.
轉載請註明出處,本文鏈接:https://www.uj5u.com/qukuanlian/347614.html
標籤:姜戈 单元测试 测试 自动化测试 python-unittest
上一篇:為什么我在django中收到錯誤“django.db.utils.OperationalError:沒有這樣的表:”?
