简单写法(松勤):
1.定义序列化器
class UserSerializer(ModelSerializer):
class Meta:
model=User
read_only_field=["id"]
# exclude=['password']
fields = "__all__"
2.定义视图集
from rest_framework.permissions import AllowAny
# 1.用户管理视图集
class UserViewSet(ModelViewSet):
queryset = User.objects.all()
serializer_class = UserSerializer
permission_classes = [AllowAny]
补充: 密码加密用 make_password
from django.contrib.auth.hashers import make_password
class UserSerializer(ModelSerializer):
"""
用户管理-序列化器
"""
class Meta:
model = User
read_only_field = ["id"]
# exclude=['password']
fields = "__all__"
def create(self, validated_data):
# 对validated_data进行处理或修改后再保存到数据库
validated_data['password']=make_password(validated_data['password'])
validated_data['is_staff']=1
return super().create(validated_data)
3.配置url
from rest_framework.routers import DefaultRouter
router=DefaultRouter()
router.register('users',views.UserViewSet)
urlpatterns = []
urlpatterns += router.urls
列表接口:
新增(注册接口)?有问题待解决
复杂点的(柠檬)
- 注册后要返回token
- 要验证密码和确认密码媳妇是你
在【users应用】中的serializers.py 中
需求:
- 需要修改User 的序列化器,吧 email 字段改成必传
- 确认密码、和token 是 模型 的额外的字段,需要添加
- 密码和确认密码需要做一个联合校验,”两次输入密码要一致“validate 中
- 用户名要求 “仅允许6-20个字符的用户名”
- 密码要求“仅允许6-20个字符的密码”
- 用户名验重(已又有的),增加email验重
- 登录成功后,返回token(要使用TokenObtainPairSerializer()的get_token(user)方法)
- User模型,新增数据,是用User.objects.create_user
- 响应只返回三个字段(id,username, token)
from rest_framework.serializers import ModelSerializer
from rest_framework import serializers
from django.contrib.auth.models import User
from rest_framework.validators import UniqueValidator
from utils.jwttoken import MyTokenObtainPairSerializer
class RegisterModelSerializer(ModelSerializer):
password_confirm = serializers.CharField(label='确认密码',help_text='确认密码',write_only=True,
max_length=20, min_length=6,
error_messages={
'min_length': '仅允许6-20个字符的密码',
'max_length': '仅允许6-20个字符的密码',
'required': '密码必填(可选)'}
)
token = serializers.CharField(label='生成token',help_text='生成token',read_only=True)
def validate(self, attrs):
password = attrs.get('password')
password_confirm = attrs.get('password_confirm')
if password != password_confirm:
raise serializers.ValidationError("确认密码和密码不一致")
return attrs
def create(self, validated_data):
# 删除多余的字段,确认密码
validated_data.pop('password_confirm')
"""这里要注意,不能用传统的 模型。object。create(), 因为这样传递的密码是没有加密的,需要用create_user"""
user = User.objects.create_user(username=validated_data.get("username"),
email=validated_data.get('email'),
password=validated_data.get('password'))
# 生成token(没有自定义的序列化器,就用from rest_framework_simplejwt.serializers import TokenObtainPairSerializer ,这个获取token序列化器)
serializers=MyTokenObtainPairSerializer()
user.token=serializers.get_token(user)
return user
class Meta:
model = User
fields = ["id","username","password","password_confirm","email","token"]
extra_kwargs = {
'username':{
'max_length':20,
'min_length':6,
'error_messages':{
'min_length': '仅允许6-20个字符的用户名',
'max_length': '仅允许6-20个字符的用户名',
'required': "名称必填"}
},
'password':{
'max_length':20,
'min_length':6,
'write_only':True,
'error_messages':{
'min_length': '仅允许6-20个字符的密码',
'max_length': '仅允许6-20个字符的密码',
'required': "密码必填"}
},
'email':{
'required':True,
'write_only': True,
'error_messages': {
'required': "邮箱必传"},
# 添加邮箱重复校验
'validators': [UniqueValidator(
queryset=User.objects.all(),
message="此邮箱已注册"
)]
}
}
views.py中,定义了视图类,继承的 GenericViewSet ,那么url中,的as_view(), 就要接收字典
from .serializers import RegisterModelSerializer
from rest_framework import generics, mixins
from rest_framework.viewsets import ModelViewSet, GenericViewSet
from django.contrib.auth.models import User
class RegisterModelView(mixins.CreateModelMixin, GenericViewSet):
serializer_class = RegisterModelSerializer
queryset = User.objects.all()
url.py中
校验用户名是否存在接口、校验邮箱是否存在接口
视图类,不是继承的Set类,url.py 中,就直接as_view就好了
from rest_framework.views import APIView
from rest_framework.response import Response
class UserNameIsExistedView(APIView):
def get(self,request,name):
count=User.objects.filter(username=name).count()
if "@" in name:
count = User.objects.filter(email=name).count()
return Response({"email":name,"count":count})
return Response({"username": name,"count":count})
# 用户名和邮箱的校验
re_path(r'^(?P<name>.{5,20})/count/$',UserNameIsExistedView.as_view())
效果: