如何从 django shell 创建用户

当我创建用户从 django-admin的用户密码是加密的。 但是当我从 django shell 创建 user 时,用户密码保存为纯文本。 例如:

{
"date_joined": "2013-08-28T04:22:56.322185",
"email": "",
"first_name": "",
"id": 5,
"is_active": true,
"is_staff": false,
"is_superuser": false,
"last_login": "2013-08-28T04:22:56.322134",
"last_name": "",
"password": "pbkdf2_sha256$10000$iGKbck9CED0b$6hWrKYiMPNGKhcfPVGal2YP4LkuP3Qwem+2ydswWACk=",
"resource_uri": "/api/v1/user/5/",
"username": "user4"
},
{
"date_joined": "2013-08-29T01:15:36.414887",
"email": "test@ophio",
"first_name": "",
"id": 6,
"is_active": true,
"is_staff": true,
"is_superuser": true,
"last_login": "2013-08-29T01:15:36.414807",
"last_name": "",
"password": "123test",
"resource_uri": "/api/v1/user/6/",
"username": "test3"
}

我正在尝试为一个简单的博客应用程序制作 REST 风格的 api: 当我尝试通过发送请求(通过传递 JSON)插入用户时,密码保存为纯文本。 如何覆盖这种行为。

105471 次浏览

You use user.set_password to set passwords in the django shell. I'm not even sure if directly setting the password via user.password would even work, since Django expects a hash of the password.

The password field doesn't store passwords; it stores them as <algorithm>$<iterations>$<salt>$<hash>, so when it checks a password, it calculates the hash, and compares it. I doubt the user actually has a password whose calculated password hash is in <algorithm>$<iterations>$<salt>$<hash> form.

If you get the json with all the information needed to create the User, you could just do

User.objects.create_user(**data)

assuming your passed json is called data.

Note: This will throw an error if you have extra or missing items in data.

If you really want to override this behavior, you can do

def override_setattr(self,name,value):
if name == 'password':
self.set_password(value)
else:
super().__setattr__(self,name,value) #or however super should be used for your version


User.__setattr__ = override_setattr

I haven't tested this solution, but it should work. Use at your own risk.

There are couple of way to set password for a django user object from django-shell.

user = User(username="django", password = "secret")
user.save()

This will store encrypted password.

user = User(username="django")
user.set_password("secret")
user.save()

This will store encrypted password.

But,

user = User(username="django")
user.password="secret"
user.save()

This will store plain text password. There is no hashing / encryptions applied since you are modifying the property directly.

You should not create the user via the normal User(...) syntax, as others have suggested. You should always use User.objects.create_user(), which takes care of setting the password properly.

user@host> manage.py shell
>>> from django.contrib.auth.models import User
>>> user=User.objects.create_user('foo', password='bar')
>>> user.is_superuser=True
>>> user.is_staff=True
>>> user.save()

Answer for those using django 1.9 or greater since from django.contrib.auth.models import User has been deprecated (possibly even earlier) but definitely by 1.9.

Instead do: in bash:

python manage.py shell

In the python shell to create a user with a password:

from django.apps import apps
User = apps.get_model('user', 'User')
me = User.objects.create(first_name='john', email='johnsemail@email.com') # other_info='other_info', etc.
me.set_password('WhateverIwant')  # this will be saved hashed and encrypted
me.save()

If coming from an API you should probably apply a Form as such:

import json
User = get_model('User')
class UserEditForm(BaseModelForm):
"""This allows for validity checking..."""


class Meta:
model = User
fields = [
'first_name', 'password', 'last_name',
'dob', # etc...
]
# collect the data from the API:
post_data = request.POST.dict()
data = {
'first_name': post_data['firstName'],
'last_name': post_data['firstName'],
'password': post_data['password'], etc.
}
dudette = User()  # (this is for create if its edit you can get the User by pk with User.objects.get(pk=kwargs.pk))
form = UserEditForm(data, request.FILES, instance=dudette)
if form.is_valid():
dudette = form.save()
else:
dudette = {'success': False, 'message': unicode(form.errors)}
return json.dumps(dudette.json())  # assumes you have a json serializer on the model called def json(self):

The fastest way creating of super user for django, type in shell:

python manage.py createsuperuser

To automate the script you can use the pipe feature to execute the list of commands without having to type it out every time.

### content of "create_user.py" file
from django.contrib.auth import get_user_model


# see ref. below
UserModel = get_user_model()


if not UserModel.objects.filter(username='foo').exists():
user=UserModel.objects.create_user('foo', password='bar')
user.is_superuser=True
user.is_staff=True
user.save()

Ref: get_user_model()

Remember to activate VirtualEnv first, then run the command below (for Linux):

cat create_user.py | python manage.py shell

If you using window then substitute the cat command with the type command

type create_user.py | python manage.py shell

OR for both Linux and Windows

# if the script is not in the same path as manage.py, then you must
#    specify the absolute path of the "create_user.py"
python manage.py shell < create_user.py

Pitfall: don't include blank lines in any of the indented blocks, think of it as you pasting your code in the REPL. If you have any empty lines it won't work.

To create Users execute:

$ python manage.py shell
>>>> from django.contrib.auth.models import User
>>>> user = User.objects.create_user('USERNAME', 'MAIL_NO_REQUIRED', 'PASSWORD')