一、项目需求
'''
1、自定义User表,新增mobile唯一约束字段,新增icon图片字段
2、在自定义user表基础上,用GenericViewSet + CreateModelMixin + serializer 完成User表新增接口(就是注册接口),需要重写create,不然密码是明文
3、在自定义user表基础上,用GenericViewSet + RetrieveModelMixin + serializer 完成User表单查(就是用户中心)
4、在自定义user表基础上,用GenericViewSet + UpdateModelMixin + serializer 完成头像修改
'''
1、models.py
from django.db import models
from django.contrib.auth.models import AbstractUser
class User(AbstractUser):
phone = models.CharField(max_length=11, unique=True) # 唯一
icon = models.ImageField(upload_to='icon', default='icon/default.png') # 需要配置media文件夹,上传的文件回到media里
2、serializer.py
from rest_framework import serializers
from api.models import User
from rest_framework.exceptions import ValidationError
class UserModelSerializer(serializers.ModelSerializer):
re_password = serializers.CharField(max_length=32, required=True, write_only=True) # 因为表里没有,需要定义一个字段
class Meta:
model = User
fields = ['username', 'password', 'phone', 're_password', 'icon']
extra_kwargs = {
'username': {'max_length': 16},
'password': {'write_only': True}
}
# 局部钩子
def validate_phone(self, data):
if not len(data) == 11:
raise ValidationError('手机号不合法')
return data
# 全局钩子
def validate(self, attrs):
if not attrs.get('password') == attrs.get('re_password'):
raise ValidationError('两次密码不一致')
# 需要去除re_password,因为表里没有re_password字段
attrs.pop('re_password')
return attrs
# 重写create方法
def create(self, validated_data):
user = User.objects.create_user(**validated_data) # 掉了会密码加密
return user
3、路由分发urls.py
# 项目
from django.contrib import admin
from django.urls import path, include,re_path
from django.views.static import serve # django内置的视图函数
from django.conf import settings
urlpatterns = [
path('admin/', admin.site.urls),
# 路由分发
path('api/', include('api.urls')),
# 开放media文件夹
re_path('media/(?P<path>.*)', serve,{'document_root':settings.MEDIA_ROOT}),
]
# app
from api import views
from rest_framework.routers import SimpleRouter # 自动生成路由
router = SimpleRouter()
router.register('register', views.RegisterView, 'register')
print(router.urls)
urlpatterns = [
# path('register/', views.RegisterView.as_view({'post':'create'})),
]
urlpatterns += router.urls
4、views.py
from django.shortcuts import render
# Create your views here.
from rest_framework.viewsets import GenericViewSet
from rest_framework.mixins import CreateModelMixin
from api.serializer import UserModelSerializer
from api.models import User
# 注册接口
class RegisterView(GenericViewSet, CreateModelMixin):
queryset = User.objects.all()
serializer_class = UserModelSerializer
5、settion.py
# 注册
INSTALLED_APPS = [
'rest_framework'
]
# 扩展user表
AUTH_USER_MODEL = 'api.user'
# 配置头像相关
MEDIA_URL = '/media/'
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
6、切换实例化类
'''
假设get请求和post请求,用的序列化类不一样,如果处理?
重写get_serializer_class,返回什么,用的就是那个序列化类
注册用的序列化类是UserModelSerializer,查询用的序列化类是RetrieveModelMixin
'''
# views.py
from rest_framework.viewsets import GenericViewSet
from rest_framework.mixins import CreateModelMixin, RetrieveModelMixin, UpdateModelMixin
from api.serializer import UserModelSerializer, UserReadOnlyModelSerializer
from api.models import User
class RegisterView(GenericViewSet, CreateModelMixin, RetrieveModelMixin):
queryset = User.objects.all()
serializer_class = UserModelSerializer
def get_serializer_class(self): # 重写这个方法
print(self.action) # create,retrieve
if self.action == 'create': # 利用action属性实现切换类
return UserModelSerializer
elif self.action == 'retrieve':
return UserReadOnlyModelSerializer
# serializer.py
class UserModelSerializer(serializers.ModelSerializer): # 跟上面的一样
class Meta:
model = User
class UserReadOnlyModelSerializer(serializers.ModelSerializer): # 新写的类
class Meta:
model = User
fields = ['username', 'icon']
7、切换头像
# views.py
from rest_framework.viewsets import GenericViewSet
from rest_framework.mixins import CreateModelMixin, RetrieveModelMixin, UpdateModelMixin
from api.serializer import UserModelSerializer, UserReadOnlyModelSerializer, UserImageModelSerializer
from api.models import User
# 使用什么功能,继承什么类
class RegisterView(GenericViewSet, CreateModelMixin, RetrieveModelMixin, UpdateModelMixin):
queryset = User.objects.all()
serializer_class = UserModelSerializer
def get_serializer_class(self):
print(self.action) # create,retrieve
if self.action == 'create':
return UserModelSerializer
elif self.action == 'retrieve':
return UserReadOnlyModelSerializer
elif self.action == 'update': # 判断是否是update,返回该序列化类
return UserImageModelSerializer
# serializer.py
class UserImageModelSerializer(serializers.ModelSerializer):
class Meta:
model = User
fields = ['icon']