【发布时间】:2016-02-16 07:29:53
【问题描述】:
我已经阅读了许多关于错误代码 400 的 SO 问题,并了解问题主要是当客户端不发送 json 时,api 正在等待。但是,我无法解决我的错误代码 400 问题。我正在关注this thinkster djangular 教程,在注册新用户部分,我遇到了错误的请求 400。
views.py
from rest_framework import permissions, viewsets, status
from rest_framework.response import Response
from authentication.models import Account
from authentication.permissions import IsAccountOwner
from authentication.serializers import AccountSerializer
class AccountViewSet(viewsets.ModelViewSet):
lookup_field = 'username'
queryset = Account.objects.all()
serializer_class = AccountSerializer
def get_permissions(self):
if self.request.method in permissions.SAFE_METHODS:
return (permissions.AllowAny(),)
if self.request.method == 'POST':
return (permissions.AllowAny(),)
return (permissions.IsAuthenticated(), IsAccountOwner(),)
def create(self, request):
serializer = self.serializer_class(data=request.data)
if serializer.is_valid():
Account.objects.create_user(**serializer.validated_data)
return Response(serializer.validated_data, status=status.HTTP_201_CREATED)
return Response({
'status': 'Bad request',
'message': 'Account could not be created with received data.'
}, status=status.HTTP_400_BAD_REQUEST)
这里的 create 方法是不是应该覆盖 CreateModelMixin 类中的 create 方法?
这是我的 serializers.py
from django.contrib.auth import update_session_auth_hash
from rest_framework import serializers
from authentication.models import Account
class AccountSerializer(serializers.ModelSerializer):
password = serializers.CharField(write_only=True, required=False)
confirm_password = serializers.CharField(write_only=True, required=False)
class Meta:
model = Account
fields = ('id', 'email', 'username', 'created_at', 'updated_at',
'first_name', 'last_name', 'tagline', 'password',
'confirm_password',)
read_only_fields = ('created_at', 'updated_at',)
def create(self, validated_data):
return Account.objects.create_user(**validated_data)
def update(self, instance, validated_data):
instance.username = validated_data.get('username', instance.username)
instance.tagline = validated_data.get('tagline', instance.tagline)
instance.save()
password = validated_data.get('password', None)
confirm_password = validated_data.get('confirm_password', None)
if password and confirm_password and password == confirm_password:
instance.set_password(password)
instance.save()
update_session_auth_hash(self.context.get('request'), instance)
return instance
当您使用序列化程序的 .save() 方法创建对象时,对象的属性按字面意思设置。这意味着使用密码“password”注册的用户将其密码存储为“password”。这有几个原因很糟糕:1)以纯文本形式存储密码是一个巨大的安全问题。 2) Django 在比较之前对密码进行哈希和加盐处理,因此用户无法使用“密码”作为密码登录。 我们通过重写此视图集的 .create() 方法并使用 Account.objects.create_user() 创建 Account 对象来解决此问题。
真的不知道发生了什么......
【问题讨论】: