Jack Evans
Jack Evans

Reputation: 1717

Django 1.9 Bulk Create New Users Not hashing Passwords Correctly

I want to read in some data from a file to quickly create many test accounts. I'd prefer to use the bulk_create method since this is typically much faster for adding many records to a model. However, when using the bulk_create method with Django's User model the passwords aren't being hashed correctly meaning I'm then unable to log in and out as a user.

    User.objects.bulk_create([
        User(
            username=name,
            email='[email protected]',
            password='Sample&Password!',
            is_active=True,
        ) for name in f.read().splitlines()
    ])

Django admin shows the following error in each User's password field

Invalid password format or unknown hashing algorithm.

The second method however continues to work (albeit much slower).

    for name in f.read().splitlines():
        User.objects.create_user(
            name,
            '[email protected]',
            password="Sample&Password!"
        ).save()

My question is, is there a way to properly bulk create users in one go in Django. Does Django behave like this for a reason or is this a bug?

Upvotes: 9

Views: 4555

Answers (2)

François Constant
François Constant

Reputation: 5496

That's because password are encrypted in the database and you're saving the original. You simply need to use make_password to encrypt it.

Please try:

from django.contrib.auth.hashers import make_password

User.objects.bulk_create([
    User(
        username=name,
        email='[email protected]',
        password=make_password('Sample&Password!'),
        is_active=True,
    ) for name in f.read().splitlines()
])

Upvotes: 1

Ken
Ken

Reputation: 795

Use make_password. This ensures that hashed passwords are stored in your database. If make_password is too slow, see this

from django.contrib.auth.hashers import make_password

User.objects.bulk_create([
    User(
        username=name,
        email='[email protected]',
        password=make_password('Sample&Password!'),
        is_active=True,
    ) for name in f.read().splitlines()
])

Upvotes: 19

Related Questions