问题描述:

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.

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.

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

Full traceback:

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

Customer user model:

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()

Custom user manager:

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

Thanks!

网友答案:

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

I realized I was actually calling

UserObject.objects.get('[email protected]')

instead of

UserObject.objects.get(email='[email protected]')

which is why the errors were being thrown. If you look into the Django source code, you'll find 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.

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

网友答案:

You have to implement has_module_perms method as stated in the Django custom user documentation:

If you want your custom User model to also work with Admin, your User model must define some additional attributes and methods.

相关阅读:
Top