1. 在建立model时对django自带的user做补充
from django.contrib.auth.models import AbstractBaseUser, PermissionsMixin
class ANUser(AbstractBaseUser, PermissionsMixin, JsonableObject):
pass
2. 在viewset中设置用户权限访问
from rest_framework import permissions, viewsets
class CompanyViewSet(views.ModelViewSet):
authentication_classes = [OAuth2Authentication, SessionAuthentication]
permission_classes = [permissions.IsAuthenticated]
queryset = Company.objects.all()
serializer_class = CompanySerializer
permission_classes就是rest framework中关于viewset的权限控制。
IsAuthenticated是用户身份验证,需要用户登录才可以拥有访问权限
IsAuthenticatedOrReadOnly用户登录可以执行所有的操作,但是用户如果没有登录的话就只有只读的权限
AllowAny是所有用户不管有没有登录都可以访问
IsAdminUser是只有管理员才有权限访问
3. 在viewset中可以使用装饰器action写新的方法,而且这个方法还会自行生成路由,不需要你重新注册,可以说是非常方便了。
from django.contrib.auth.models import User
from rest_framework import status, viewsets
from rest_framework.decorators import action
from rest_framework.response import Response
from myapp.serializers import UserSerializer, PasswordSerializer
class UserViewSet(viewsets.ModelViewSet):
"""
A viewset that provides the standard actions
"""
queryset = User.objects.all()
serializer_class = UserSerializer
@action(detail=True, methods=['post'])
def set_password(self, request, pk=None):
user = self.get_object()
serializer = PasswordSerializer(data=request.data)
if serializer.is_valid():
user.set_password(serializer.data['password'])
user.save()
return Response({'status': 'password set'})
else:
return Response(serializer.errors,
status=status.HTTP_400_BAD_REQUEST)
@action(detail=False)
def recent_users(self, request):
recent_users = User.objects.all().order_by('-last_login')
page = self.paginate_queryset(recent_users)
if page is not None:
serializer = self.get_serializer(page, many=True)
return self.get_paginated_response(serializer.data)
serializer = self.get_serializer(recent_users, many=True)
return Response(serializer.data)
以上是官方文档给出的例子,其中detail=True or detail=False指的是该额外的操作针对的是一个对象还是集合,也就是对应的路由/user/recent_users还是/user/{pk}/recent_users。methods是确定该操作的请求方法。其他的全凭自己发挥。
4. 有些create or update方法需要在序列化器中实现:
ForeignKey
class UserSerializer(serializers.ModelSerializer):
profile = ProfileSerializer()
class Meta:
model = User
fields = ('username', 'email', 'profile')
def create(self, validated_data):
profile_data = validated_data.pop('profile')
user = User.objects.create(**validated_data)
Profile.objects.create(user=user, **profile_data)
return user
或者是:ManyToManyField
class User(models.Model):
profile = models.ManyToManyField(Profile)
class UserSerializer(serializers.ModelSerializer):
profile = ProfileSerializer()
class Meta:
model = User
fields = ('username', 'email', 'profile')
def create(self, validated_data):
profile_data = validated_data.pop('profile')
user = User.objects.create(**validated_data)
for profile in profile_data:
p = Profile.objects.create(**profile_data)
user.profile.add(p)
return user
5. 在序列化器中序列化的时候可以自定义,例如:
class UserSerializer(serializers.ModelSerializer):
profile = ProfileSerializer()
username = serializers.SerializerMethodField()
def get_username(self, obj):
return obj.username + obj.name
class Meta:
model = User
fields = ('username', 'email', 'profile')
6. 在django中创建的用户,用户的密码一般使用哈希加密之后存放在数据库中,在用户修改密码的时候
class ProfileUpdateViewSet(generics.UpdateAPIView):
authentication_classes = [OAuth2Authentication, SessionAuthentication]
permission_classes = [permissions.IsAuthenticated]
serializer_class = PasswordSerializer
def update(self, request, pk=None, *args, **kwargs):
user = self.request.user
serializer = PasswordSerializer(data=request.data)
if serializer.is_valid():
if serializer.data['password'] == serializer.data['confirm']:
if check_password(serializer.data['old'], user.password):
user.set_password(serializer.data['password'])
user.save()
return Response('password set')
else:
return Response('The old password error', status=status.HTTP_400_BAD_REQUEST)
else:
return Response('The two passwords you entered did not match', status=status.HTTP_400_BAD_REQUEST)
else:
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
使用check_password()来判段密码是否正确,用user.set_password来给用户设置密码,用make_password()将普通的字符串密码转化为哈希格式,可以直接存入数据库。
7. 其中有的表支持中文搜索,而有的表不支持,提示OperationalError: (1271, "Illegal mix of collations for operation 'like'")的错误
找到django包下面的\site-packages\django\db\backends\mysql\base.py文件并编辑,将operators下的icontains对应的值修改为'LIKE BINARY %s'
operators = {
'exact': '= %s',
'iexact': 'LIKE %s',
'contains': 'LIKE BINARY %s',
'icontains': 'LIKE BINARY %s',
'gt': '> %s',
'gte': '>= %s',
'lt': '< %s',
'lte': '<= %s',
'startswith': 'LIKE BINARY %s',
'endswith': 'LIKE BINARY %s',
'istartswith': 'LIKE %s',
'iendswith': 'LIKE %s',
}