Я делаю системные сохраненные пользовательские данные для модели. Я хочу написать часть логики в views.py и часть сохраненных данных в сериализаторе. Я хочу, чтобы системный пароль был изменен на хэш. Теперь я написал коды в представлениях. .py,
class InfoViews(viewsets.ModelViewSet):
queryset = Info.objects.all()
serializer_class = InfoSerializer
lookup_field = 'id'
def create(self,request, *args, **kwargs):
user = Info()
passwd = request.data['password']
md5 = hashlib.md5()
md5.update(passwd.encode('utf-8'))
user.password = md5.hexdigest()
user.save()
return JsonResponse({"data":"data"})
в serializer.py
class InfoSerializer(serializers.ModelSerializer):
created_time = serializers.DateTimeField(required=False)
class Meta:
model = Info
fields = '__all__'
def create(self, validated_data):
user = Info(
email=validated_data['email'],
username=validated_data['username'],
)
user.set_password(validated_data['password'])
user.save()
return user
в models.py
class Info(models.Model):
username = custom_fields.NotEmptyCharField(max_length=100, unique=True)
email = models.EmailField()
password = custom_fields.NotEmptyCharField(max_length=100)
class Meta:
db_table = 'info'
def __str__(self):
return '%s: %s' % (self.username, self.email)
Теперь, когда я пытался сохранить данные пользователя в модели, возникает ошибка django.core.exceptions.ValidationError: ['Can not be empty!']. Что не так в моих кодах? Я искал http://www.django-rest-framework.org/api-guide/serializers/. Как мне это исправить?






Вы получаете сообщение об ошибке проверки, потому что поле email является обязательным. Когда вы запускаете user.save(), значение email не отправляется, следовательно, ValidationError.
Вы определенно должны сохранять все, что находится в вашем представлении, сериализатор - это просто способ изменить способ представления данных в DRF.
Кроме того, вам действительно не следует использовать md5 для сохранения паролей. Просто используйте встроенный метод Django: user.set_password(password) - Django позаботится о хешировании за вас, причем гораздо более безопасно.
Вы не используете сериализатор InfoSerializer(), поэтому удалите из него метод create() и измените свой views.py, как показано ниже,
class InfoViews(ModelViewSet):
queryset = Info.objects.all()
serializer_class = InfoSerializer
lookup_field = 'id'
def create(self, request, *args, **kwargs):
serializer = InfoSerializer(request.data).data
serializer.pop('created_time', None)
passwd = serializer['password']
md5 = hashlib.md5()
md5.update(passwd.encode('utf-8'))
serializer['password'] = md5.hexdigest()
Info.objects.create(**serializer)
return JsonResponse({"data": "data"})
Мое дружеское предложение
Я не думаю, что это хороший способ добиться успеха, поэтому изменения ниже пойдут лучше (я так думаю;))
views.py
class InfoViews(ModelViewSet):
queryset = Info.objects.all()
serializer_class = InfoSerializer
lookup_field = 'id'
serializer.py
import hashlib
class InfoSerializer(serializers.ModelSerializer):
created_time = serializers.DateTimeField(required=False)
def set_password(self, raw_pwd):
md5 = hashlib.md5()
md5.update(raw_pwd.encode('utf-8'))
return md5.hexdigest()
class Meta:
model = Info
fields = '__all__'
def create(self, validated_data):
validated_data['password'] = self.set_password(validated_data['password'])
return super().create(validated_data)
Обновлять
Альтернативный create() для сериализатора,
def create(self, validated_data):
validated_data['password'] = self.set_password(validated_data['password'])
user = Info.objects.create(
email=validated_data['email'],
username=validated_data['username'],
password=validated_data['password']
)
# you can avoid large number of assignment statements (as above) by simply calling "super()" method
return user
спасибо за ваш ответ. У меня один вопрос, почему вы добавили super () super().create(validated_data) в свой serializer.py?
Он создаст и вернет экземпляр Info с предоставленным validated_data. Используя это, вы можете избежать assignment statements
посмотрите на часть ответа Обновлять.
Не по теме вашего вопроса, но вам абсолютно не следует использовать MD5 для хеширования паролей, если вы не поддерживаете устаревшую систему или не имеете очень специфического варианта использования. Как сказал @hammygoonan, вы должны использовать встроенный метод django
User.set_password.