Django:“要解压的值太多”调用user.objects.get()时 [英] Django: "Too many values to unpack" when calling user.objects.get()

查看:161
本文介绍了Django:“要解压的值太多”调用user.objects.get()时的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在Django 1.6中,我定义了一个自定义用户模型,但是由于某种原因,当我创建一个超级用户并尝试获取该超级用户或以该超级用户身份访问Django admin时,得到了这个 ValueError :要解包的值太多。我仔细阅读了许多与此错误类似的问题,但没有找到适合我特定问题的内容。我不知道出什么问题。

In Django 1.6, I've defined a custom user model, but for some reason now when I create a superuser and try to get it or access the Django admin as that superuser, I get this ValueError: Too many values to unpack. I have perused the many similar questions on SO about this error and haven't found anything that fits my particular issue. I cannot figure out what would be wrong.

在我的自定义 create_user create_superuser 在自定义管理器中的方法中,我确实传递了一个额外的字段,但是该字段实际上并未进入模型中,因此我看不到为什么会引起问题。

In my custom create_user and create_superuser methods in the custom manager, I do pass an extra field, but that field does not actually make it into the model, so I can't see why that would be causing a problem.

此外,尝试访问管理员时,我得到一个略有不同的错误: AttributeError:'UserObject'没有属性'has_module_perms'

Additionally, when trying to access the admin, I get a slightly different error: AttributeError: 'UserObject' has no attribute 'has_module_perms'.

完整追溯:

Traceback (most recent call last):
  File "<console>", line 1, in <module>
  File "C:\Users\JJ\Coding\virtualenvs\TCR5venv\lib\site-packages\django\db\models\manager.py", line 151, in get
    return self.get_queryset().get(*args, **kwargs)
  File "C:\Users\JJ\Coding\virtualenvs\TCR5venv\lib\site-packages\django\db\models\query.py", line 298, in get
    clone = self.filter(*args, **kwargs)
  File "C:\Users\JJ\Coding\virtualenvs\TCR5venv\lib\site-packages\django\db\models\query.py", line 590, in filter
    return self._filter_or_exclude(False, *args, **kwargs)
  File "C:\Users\JJ\Coding\virtualenvs\TCR5venv\lib\site-packages\django\db\models\query.py", line 608, in _filter_or_exclude
    clone.query.add_q(Q(*args, **kwargs))
  File "C:\Users\JJ\Coding\virtualenvs\TCR5venv\lib\site-packages\django\db\models\sql\query.py", line 1198, in add_q
    clause = self._add_q(where_part, used_aliases)
  File "C:\Users\JJ\Coding\virtualenvs\TCR5venv\lib\site-packages\django\db\models\sql\query.py", line 1232, in _add_q
    current_negated=current_negated)
  File "C:\Users\JJ\Coding\virtualenvs\TCR5venv\lib\site-packages\django\db\models\sql\query.py", line 1035, in build_filter
    arg, value = filter_expr
ValueError: too many values to unpack

客户用户模型:

class UserObject(AbstractBaseUser):

    email = models.EmailField(max_length=254, unique=True, db_index=True)

    USERNAME_FIELD = 'email'
    # REQUIRED_FIELDS = ['student_or_business',]

    # Tells us whether the UserObject is a business or student
    @property
    def type(self):
        if hasattr(self, 'Student'.lower()):
            return 'S'
        elif hasattr(self, 'BusinessHandler'.lower()):
            return 'B'
        else:
            raise TypeError, "UserObject has neither Student nor BusinessHandler connected."

    # Gets us the actual UserObject's accompanying object, whether Student or Business
    @property
    def get_profile_object(self):
        if self.type == 'S':
            return getattr(self, 'Student'.lower())
        elif self.type == 'B':
            return getattr(self, 'BusinessHandler'.lower()) # to take advantage of refactoring

    @property
    def is_student(self):
        return self.type == 'S'

    @property
    def is_business(self):
        return self.type == 'B'

    def relevant_item(self, input_tuple):
        '''
        Takes in a tuple of options for return in form (Student, Business[, other]).
        Returns the appropriate option depending
        '''
        if not 2 <= len(input_tuple) <= 3:
            raise TypeError, "relevant_item() requires a tuple of 2 or 3."
        else:
            if self.type == 'S':
                return input_tuple[0]
            elif self.type == 'B':
                return input_tuple[1]
            else:
                return input_tuple[2] if len(input_tuple) == 3 else None


    signup_date = models.DateTimeField(auto_now_add=True)

    # admin stuff
    is_active = models.BooleanField(default=True)
    is_admin = models.BooleanField(default=False)
    is_staff = models.BooleanField(default=False)

    # Settings
    verified = models.BooleanField(default=False)
    accepted_TOS = models.DateField(default=datetime.datetime.today())
         # Date so can find who need to update when change TOS

    # Temporary hashes/strings
    verification_id = models.CharField(unique=True, default=lambda: random_string(20), max_length=20)
    reset_password_code = models.CharField(blank=True, default=lambda: random_string(20), max_length=20)

    def get_new_reset_password_code(self):
        self.reset_password_code = random_string(20)
        self.save()
        return self.reset_password_code

    def new_verification_id(self):
        self.verification_id = random_string(20)
        try:
            self.save()
        except IntegrityError:
            self.new_verification_id()

    objects = UserObjectManager()

自定义用户管理器:

class UserObjectManager(BaseUserManager):

    @staticmethod
    def create_accompanying_model(user, student_or_business):
        '''
        This creates the appropriate accompanying Student or BusinessHandler model when a
        new UserObject is created.
        '''

        if student_or_business == 'S':
            s = models.get_model('student', 'Student')
            new_item = s.objects.create(user_object=user, UserObject_creation=True)
            new_item.save()

        elif student_or_business == 'B':
            b = models.get_model('business', 'BusinessHandler')
            new_item = b.objects.create(user_object=user, UserObject_creation=True)
            new_item.save()

        else:
            msg = 'Must be Student or BusinessHandler.'
            raise ValueError(msg)

    def create_user(self, email, password, student_or_business):

        # normalize student_or_business
        if student_or_business.lower() in ('s', 'student'):
            student_or_business = 'S'
        elif student_or_business.lower() in ('b', 'business', 'BusinessHandler'.lower()):
            student_or_business = 'B'

        # Check if an email was provided
        if not email:
            msg = 'Users must have an email address.'
            raise ValueError(msg)

        # If a student, check if a '.edu' email address was provided
        if email and student_or_business == 'S':
            if not email.endswith('.edu'):
                msg = 'Students must sign up with a .edu email address.'
                raise ValueError(msg)

        user = self.model(
            email=UserObjectManager.normalize_email(email),

            # Removed the below because calculating that differently
            # student_or_business = student_or_business,

        )

        user.set_password(password)
        user.save(using=self._db)

        self.create_accompanying_model(user, student_or_business)

        return user

    def create_superuser(self, email, password, student_or_business):
        user = self.create_user(email, password, student_or_business)
        user.is_admin = True
        user.is_staff = True
        user.is_superuser = True
        user.save(using=self._db)
        return user

谢谢!

推荐答案

事实证明,这里的问题实际上与引发的错误无关。

Turns out that the problem here was actually very unrelated to the errors thrown.

我意识到我实际上是在呼叫

I realized I was actually calling

UserObject.objects.get('user@email.com')

而不是

UserObject.objects.get(email='user@email.com')

这就是为什么错误被抛出。如果查看Django源代码,您会发现在为 QuerySet 构建过滤器时,Django会解压缩要在过滤器中使用的字段名称和数据,但是由于我没有为 objects.get(...)提供任何字段名,解包时抛出错误。

which is why the errors were being thrown. If you look into the Django source code, you'll find that when building a filter for a QuerySet, Django unpacks the field name and data for use in the filter, but since I had provided no field name to objects.get(...), there was an error thrown when unpacking.

为此使用了Werkzeug实时浏览器调试器;我强烈推荐它。

Used the Werkzeug live browser debugger for this; I highly recommend it.

这篇关于Django:“要解压的值太多”调用user.objects.get()时的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆