Python Mixer.blend()模块无法正确创建引用UUID为PK的自定义用户对象的实例

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

我正在尝试使用pytest对我的模型进行测试。我在“:memory:”数据库中的SQLite3上使用混合器时遇到问题

我有一个名为Category的模型,它有一个外键属性“created_by”,它引用了我的自定义用户模型

在mixer.blend()中将用户的引用模型分配给category变量时,我得到一个异常,该异常表示用户实例不是UUID的实例

请参阅下面我的测试:

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."]