1 自定义User表扩展auth的User,新增mobile唯一约束字段;新增icon图片字段
2 在自定义User表基础上,用 GenericViewSet + CreateModelMixin + serializer 完成User表新增接口(就是注册接口)
(重要提示:序列化类要重写create方法,不然密码就是明文了)
3 在自定义User表基础上,用 GenericViewSet + RetrieveModelMixin + serializer 完成User表单查(就是用户中心)
4 在自定义User表基础上,用 GenericViewSet + UpdateModelMixin + serializer 完成用户头像的修改
models.py --->数据迁移
from django.db import models
from django.contrib.auth.models import AbstractUser
class UserInfo(AbstractUser):
mobile = models.CharField(max_length=32, unique=True)
icon = models.ImageField(upload_to='head', default='head/default.png')
settings.py
INSTALLED_APPS = [
'rest_framework'
#打开media路径
MEDIA_URL = '/media/'
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
#扩写auth_user表
AUTH_USER_MODEL = 'app01.UserInfo'
views.py
from django.shortcuts import render
from app01.models import UserInfo
from app01.serializer import UserModelSerializer, UserReadOnlyModelSerializer, UserIconModelSerializer
from rest_framework.mixins import CreateModelMixin, RetrieveModelMixin, UpdateModelMixin
from rest_framework.generics import GenericAPIView
from rest_framework.viewsets import GenericViewSet, ViewSetMixin
# ViewSetMixin:路由写法变了,自动生成路由
# GenericAPIView:必须指定queryset和serializer
class UserView(GenericViewSet, CreateModelMixin, RetrieveModelMixin, UpdateModelMixin):
# class UserView(ViewSetMixin,GenericAPIView,CreateModelMixin):
queryset = UserInfo.objects.all()
serializer_class = UserModelSerializer
# 重写get_serializer_class方法,实现不同的请求,返回的序列化类不一样
def get_serializer_class(self):
# 可以根据请求方式
if self.action == 'create':
return UserModelSerializer
elif self.action == 'retrieve':
return UserReadOnlyModelSerializer
#更改头像
elif self.action == 'update':
return UserIconModelSerializer
serializer.py
from rest_framework import serializers
from app01.models import UserInfo
from rest_framework.exceptions import ValidationError
class UserModelSerializer(serializers.ModelSerializer):
# 注册功能,需要的字段
# username,password,re_password,mobile
# 这个字段在表中没有,写成write_only=True
re_password = serializers.CharField(max_length=18, min_length=3, required=True, write_only=True)
class Meta:
model = UserInfo
fields = ['username', 'password', 'mobile', 're_password', 'icon']
extra_kwargs = {
'username': {'max_length': 12, 'min_length': 3},
'password': {'write_only': True},
'icon': {'read_only': True}
# 写mobile的局部钩子
def validate_mobile(self, data):
if len(data) == 11:
return data
else:
raise ValidationError('手机号不合法')
# 全局钩子校验两次密码是否一致
def validate(self, attrs):
password = attrs.get('password')
re_password = attrs.get('re_password')
if password == re_password:
# re_password不存数据库,剔除
attrs.pop('re_password')
return attrs
else:
raise ValidationError('两次密码不一致')
## 重写create方法,实现密码的加密
#序列化类要重写create方法,不然密码就是明文了
def create(self, validated_data):
# re_password也可也在这里移除
# UserInfo.objects.create(**validated_data) # 密码是明文
user = UserInfo.objects.create_user(**validated_data)
return user # 注意不要忘了这句话
# 序列化的时候后
# 一个模型类,不一定对着一个序列化类
# 只做序列化用
class UserReadOnlyModelSerializer(serializers.ModelSerializer):
class Meta:
model = UserInfo
fields = ['username', 'mobile', 'icon', 'email', 'date_joined']
# 这个序列化类,只做修改头像用
class UserIconModelSerializer(serializers.ModelSerializer):
class Meta:
model = UserInfo
fields = ['icon', ]
路由分发app01/urls.py
from app01 import views
# 自动生成路由
from rest_framework.routers import SimpleRouter
router = SimpleRouter()
router.register('user', views.UserView)
# router.register('userinfo', views.UserReadOnlyView)
urlpatterns = [
urlpatterns += router.urls
总路由urls.py
from django.contrib import admin
from django.urls import path,include,re_path
from django.views.static import serve
from django.conf import settings
urlpatterns = [
path('admin/', admin.site.urls),
path('homework/', include('app01.urls')),
re_path('media/(?P<path>.*)', serve, {'document_root': settings.MEDIA_ROOT}),