Python Mixer.blend()模块无法正确创建引用UUID为PK的自定义用户对象的实例
我正在尝试使用pytest对我的模型进行测试。我在“:memory:”数据库中的SQLite3上使用混合器时遇到问题 我有一个名为Category的模型,它有一个外键属性“created_by”,它引用了我的自定义用户模型 在mixer.blend()中将用户的引用模型分配给category变量时,我得到一个异常,该异常表示用户实例不是UUID的实例 请参阅下面我的测试:Python Mixer.blend()模块无法正确创建引用UUID为PK的自定义用户对象的实例,python,django,pytest,uuid,django-mixer,Python,Django,Pytest,Uuid,Django Mixer,我正在尝试使用pytest对我的模型进行测试。我在“:memory:”数据库中的SQLite3上使用混合器时遇到问题 我有一个名为Category的模型,它有一个外键属性“created_by”,它引用了我的自定义用户模型 在mixer.blend()中将用户的引用模型分配给category变量时,我得到一个异常,该异常表示用户实例不是UUID的实例 请参阅下面我的测试: import pytest from mixer.backend.django import mixer from app
import pytest
from mixer.backend.django import mixer
from apps.API import models
pytestmark = pytest.mark.django_db
class TestCategory():
def test_model(self):
category = mixer.blend(models.Category)
assert category.pk == 1, 'Should create a Category instance'
这是非常奇怪的,因为它以前工作过(大约一周前)。为什么mixer不能从我的用户对象的主键强制UUID
如果有人有什么想法,我洗耳恭听。下面我定义了我的模型,并展示了一些堆栈跟踪。希望我们能找到一些见解
以下是pytest中的堆栈跟踪:
self = <django.db.models.fields.UUIDField: id>, value = <User: doliver@smith.com>
def to_python(self, value):
if value is not None and not isinstance(value, uuid.UUID):
try:
> return uuid.UUID(value)
venv/lib/python3.6/site-packages/django/db/models/fields/__init__.py:2325:
self = <[AttributeError("'UUID' object has no attribute 'int'") raised in repr()] UUID object at 0x7feeebf18f98>, hex = <User: doliver@smith.com>, bytes = None, bytes_le = None
fields = None, int = None, version = None
def __init__(self, hex=None, bytes=None, bytes_le=None, fields=None,
int=None, version=None):
r"""Create a UUID from either a string of 32 hexadecimal digits,
a string of 16 bytes as the 'bytes' argument, a string of 16 bytes
in little-endian order as the 'bytes_le' argument, a tuple of six
integers (32-bit time_low, 16-bit time_mid, 16-bit time_hi_version,
8-bit clock_seq_hi_variant, 8-bit clock_seq_low, 48-bit node) as
the 'fields' argument, or a single 128-bit integer as the 'int'
argument. When a string of hex digits is given, curly braces,
hyphens, and a URN prefix are all optional. For example, these
expressions all yield the same UUID:
UUID('{12345678-1234-5678-1234-567812345678}')
UUID('12345678123456781234567812345678')
UUID('urn:uuid:12345678-1234-5678-1234-567812345678')
UUID(bytes='\x12\x34\x56\x78'*4)
UUID(bytes_le='\x78\x56\x34\x12\x34\x12\x78\x56' +
'\x12\x34\x56\x78\x12\x34\x56\x78')
UUID(fields=(0x12345678, 0x1234, 0x5678, 0x12, 0x34, 0x567812345678))
UUID(int=0x12345678123456781234567812345678)
Exactly one of 'hex', 'bytes', 'bytes_le', 'fields', or 'int' must
be given. The 'version' argument is optional; if given, the resulting
UUID will have its variant and version set according to RFC 4122,
overriding the given 'hex', 'bytes', 'bytes_le', 'fields', or 'int'.
"""
if [hex, bytes, bytes_le, fields, int].count(None) != 4:
raise TypeError('one of the hex, bytes, bytes_le, fields, '
'or int arguments must be given')
if hex is not None:
> hex = hex.replace('urn:', '').replace('uuid:', '')
E AttributeError: 'User' object has no attribute 'replace'
/usr/lib/python3.6/uuid.py:137: AttributeError
During handling of the above exception, another exception occurred:
self = <apps.API.tests.test_models.TestCategory object at 0x7feeef113a58>
def test_model(self):
> category = mixer.blend(models.Category)
apps/API/tests/test_models.py:13:
venv/lib/python3.6/site-packages/mixer/main.py:568: in blend
return type_mixer.blend(**values)
venv/lib/python3.6/site-packages/mixer/main.py:116: in blend
for name, value in defaults.items()
venv/lib/python3.6/site-packages/mixer/main.py:116: in <genexpr>
for name, value in defaults.items()
venv/lib/python3.6/site-packages/mixer/mix_types.py:222: in gen_value
return type_mixer.gen_field(field)
venv/lib/python3.6/site-packages/mixer/backend/django.py:270: in gen_field
return super(TypeMixer, self).gen_field(field)
venv/lib/python3.6/site-packages/mixer/main.py:193: in gen_field
return self.gen_value(field.name, field, unique=unique)
venv/lib/python3.6/site-packages/mixer/main.py:261: in gen_value
return self.get_value(field_name, value)
venv/lib/python3.6/site-packages/mixer/backend/django.py:218: in get_value
return self._get_value(name, value, field)
venv/lib/python3.6/site-packages/mixer/backend/django.py:233: in _get_value
value = field.scheme.to_python(value)
venv/lib/python3.6/site-packages/django/db/models/fields/related.py:874: in to_python
return self.target_field.to_python(value)
self = <django.db.models.fields.UUIDField: id>, value = <User: doliver@smith.com>
def to_python(self, value):
if value is not None and not isinstance(value, uuid.UUID):
try:
return uuid.UUID(value)
except (AttributeError, ValueError):
raise exceptions.ValidationError(
self.error_messages['invalid'],
code='invalid',
> params={'value': value},
)
E django.core.exceptions.ValidationError: ["'doliver@smith.com' is not a valid UUID."]
venv/lib/python3.6/site-packages/django/db/models/fields/__init__.py:2330: ValidationError
我的用户模型使用UUID作为主键
下面是我正在使用的两个模型(类别和用户)
我在类别中的抽象BaseModel继承只包括基本信息,如创建日期、是否处于活动状态等
类别:
# django
from django.conf import settings
from django.db import models
from django.utils.translation import ugettext_lazy as _
# models
from apps.API.models.BaseModel import BaseModel
class Category(BaseModel):
CATEGORIES = (
# choices tuples go here
)
category = models.CharField(_('category'),
choices=CATEGORIES,
max_length=80,
blank=False,
db_index=True
)
created_by = models.ForeignKey(settings.AUTH_USER_MODEL,
on_delete=models.SET(
BaseModel.get_sentinel_user),
blank=False,
editable=False,
db_index=True,
related_name=(
'created_categories')
)
class Meta:
app_label = "API"
verbose_name = _('Category')
verbose_name_plural = _('Categories')
def __str__(self):
return '{}'.format(self.category)
以下是我的用户模型:
import uuid
# django
from django.contrib.auth.models import PermissionsMixin
from django.contrib.auth.models import AbstractBaseUser
from django.db import models
from django.utils.translation import ugettext_lazy as _
# models
from apps.API.models.BaseModel import BaseModel
from apps.API.manager import UserManager
class User(AbstractBaseUser, PermissionsMixin):
# Use UUID to make the merging of tables much easier if need be.
id = models.UUIDField(primary_key=True,
editable=False,
default=uuid.uuid4,
verbose_name='public identifier',)
email = models.EmailField(_('email address'), unique=True)
first_name = models.CharField(_('first name'),
max_length=255,
blank=True)
last_name = models.CharField(_('last name'),
max_length=255,
blank=True)
created_date = models.DateTimeField(_('created date'),
auto_now_add=True)
is_active = models.BooleanField(_('active'), default=True)
is_superuser = models.BooleanField(_('superuser'), default=False)
is_staff = models.BooleanField(_('staff'), default=False)
objects = UserManager()
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = []
class Meta:
app_label = "API"
verbose_name = _('User')
verbose_name_plural = _('Users')
def __str__(self):
return '{}'.format(self.email)
我突然进入Django shell,发现mixer也有同样的问题,所以这不是pytest的问题
Traceback (most recent call last):
File "/home/users/myname/dev/blah-django-app/venv/lib/python3.6/site-
packages/django/db/models/fields/__init__.py", line 2325, in to_python
return uuid.UUID(value)
File "/usr/lib/python3.6/uuid.py", line 137, in __init__
hex = hex.replace('urn:', '').replace('uuid:', '')
AttributeError: 'User' object has no attribute 'replace'
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "<console>", line 1, in <module>
File "/home/users/myname/dev/blah-django-app/venv/lib/python3.6/site-packages/mixer/main.py", line 568, in blend
return type_mixer.blend(**values)
File "/home/users/myname/dev/blah-django-app/venv/lib/python3.6/site-packages/mixer/main.py", line 116, in blend
for name, value in defaults.items()
File "/home/users/myname/dev/blah-django-app/venv/lib/python3.6/site-packages/mixer/main.py", line 116, in <genexpr>
for name, value in defaults.items()
File "/home/users/myname/dev/blah-django-app/venv/lib/python3.6/site-packages/mixer/mix_types.py", line 222, in gen_value
return type_mixer.gen_field(field)
File "/home/users/myname/dev/blah-django-app/venv/lib/python3.6/site-packages/mixer/backend/django.py", line 270, in gen_field
return super(TypeMixer, self).gen_field(field)
File "/home/users/myname/dev/blah-django-app/venv/lib/python3.6/site-packages/mixer/main.py", line 193, in gen_field
return self.gen_value(field.name, field, unique=unique)
File "/home/users/myname/dev/blah-django-app/venv/lib/python3.6/site-packages/mixer/main.py", line 261, in gen_value
return self.get_value(field_name, value)
File "/home/users/myname/dev/blah-django-app/venv/lib/python3.6/site-packages/mixer/backend/django.py", line 218, in get_value
return self._get_value(name, value, field)
File "/home/users/myname/dev/blah-django-app/venv/lib/python3.6/site-packages/mixer/backend/django.py", line 233, in _get_value
value = field.scheme.to_python(value)
File "/home/users/myname/dev/blah-django-app/venv/lib/python3.6/site-packages/django/db/models/fields/related.py", line 874, in to_python
return self.target_field.to_python(value)
File "/home/users/myname/dev/blah-django-app/venv/lib/python3.6/site-packages/django/db/models/fields/__init__.py", line 2330, in to_python
params={'value': value},
django.core.exceptions.ValidationError: ["'michaela32@yahoo.com' is not a valid UUID."]
回溯(最近一次呼叫最后一次):
文件“/home/users/myname/dev/blah-django-app/venv/lib/python3.6/site-
packages/django/db/models/fields/_init__.py”,第2325行,在to_python中
返回uuid.uuid(值)
文件“/usr/lib/python3.6/uuid.py”,第137行,在__
hex=hex.replace('urn:','').replace('uuid:','')
AttributeError:“用户”对象没有属性“替换”
在处理上述异常期间,发生了另一个异常:
回溯(最近一次呼叫最后一次):
文件“”,第1行,在
文件“/home/users/myname/dev/blah-django-app/venv/lib/python3.6/site-packages/mixer/main.py”,第568行,混合格式
返回类型_mixer.blend(**值)
文件“/home/users/myname/dev/blah-django-app/venv/lib/python3.6/site-packages/mixer/main.py”,第116行,混合格式
默认值中的name和value.items()
文件“/home/users/myname/dev/blah-django-app/venv/lib/python3.6/site-packages/mixer/main.py”,第116行,在
默认值中的name和value.items()
文件“/home/users/myname/dev/blah django app/venv/lib/python3.6/site packages/mixer/mix_types.py”,第222行,以gen_值表示
返回类型\u混合器。gen\u字段(字段)
文件“/home/users/myname/dev/blah-django-app/venv/lib/python3.6/site-packages/mixer/backend/django.py”,第270行,在gen_字段中
返回super(TypeMixer,self).gen_字段(field)
文件“/home/users/myname/dev/blah-django-app/venv/lib/python3.6/site-packages/mixer/main.py”,第193行,在gen_字段中
返回self.gen_值(field.name,field,unique=unique)
文件“/home/users/myname/dev/blah-django-app/venv/lib/python3.6/site-packages/mixer/main.py”,第261行,gen_值
返回self.get\u值(字段名称、值)
文件“/home/users/myname/dev/blah-django-app/venv/lib/python3.6/site-packages/mixer/backend/django.py”,第218行,在get_值中
返回self.\u获取\u值(名称、值、字段)
文件“/home/users/myname/dev/blah-django-app/venv/lib/python3.6/site-packages/mixer/backend/django.py”,第233行,在“获取”值中
value=field.scheme.to_python(值)
文件“/home/users/myname/dev/blah-django-app/venv/lib/python3.6/site-packages/django/db/models/fields/related.py”,第874行,在python中
将self.target\u field.to\u python(值)返回
文件“/home/users/myname/dev/blah-django-app/venv/lib/python3.6/site-packages/django/db/models/fields/__-init_;.py”,第2330行,在python中
params={'value':value},
django.core.exceptions.ValidationError:[“'michaela32@yahoo.com'不是有效的UUID。“]
这似乎是一个版本控制问题,因为Mixer还不支持Django 2.1
据推测,这次公关将解决这个问题。不确定何时或是否合并,因为5个月来没有更新混合回购协议
Traceback (most recent call last):
File "/home/users/myname/dev/blah-django-app/venv/lib/python3.6/site-
packages/django/db/models/fields/__init__.py", line 2325, in to_python
return uuid.UUID(value)
File "/usr/lib/python3.6/uuid.py", line 137, in __init__
hex = hex.replace('urn:', '').replace('uuid:', '')
AttributeError: 'User' object has no attribute 'replace'
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "<console>", line 1, in <module>
File "/home/users/myname/dev/blah-django-app/venv/lib/python3.6/site-packages/mixer/main.py", line 568, in blend
return type_mixer.blend(**values)
File "/home/users/myname/dev/blah-django-app/venv/lib/python3.6/site-packages/mixer/main.py", line 116, in blend
for name, value in defaults.items()
File "/home/users/myname/dev/blah-django-app/venv/lib/python3.6/site-packages/mixer/main.py", line 116, in <genexpr>
for name, value in defaults.items()
File "/home/users/myname/dev/blah-django-app/venv/lib/python3.6/site-packages/mixer/mix_types.py", line 222, in gen_value
return type_mixer.gen_field(field)
File "/home/users/myname/dev/blah-django-app/venv/lib/python3.6/site-packages/mixer/backend/django.py", line 270, in gen_field
return super(TypeMixer, self).gen_field(field)
File "/home/users/myname/dev/blah-django-app/venv/lib/python3.6/site-packages/mixer/main.py", line 193, in gen_field
return self.gen_value(field.name, field, unique=unique)
File "/home/users/myname/dev/blah-django-app/venv/lib/python3.6/site-packages/mixer/main.py", line 261, in gen_value
return self.get_value(field_name, value)
File "/home/users/myname/dev/blah-django-app/venv/lib/python3.6/site-packages/mixer/backend/django.py", line 218, in get_value
return self._get_value(name, value, field)
File "/home/users/myname/dev/blah-django-app/venv/lib/python3.6/site-packages/mixer/backend/django.py", line 233, in _get_value
value = field.scheme.to_python(value)
File "/home/users/myname/dev/blah-django-app/venv/lib/python3.6/site-packages/django/db/models/fields/related.py", line 874, in to_python
return self.target_field.to_python(value)
File "/home/users/myname/dev/blah-django-app/venv/lib/python3.6/site-packages/django/db/models/fields/__init__.py", line 2330, in to_python
params={'value': value},
django.core.exceptions.ValidationError: ["'michaela32@yahoo.com' is not a valid UUID."]