目录
编写登录接口
models.py
from django.db import models
# Create your models here.
class User(models.Model):
username = models.CharField(max_length=32)
password = models.CharField(max_length=32)
class UserToken(models.Model):
token = models.CharField(max_length=32)
user = models.OneToOneField(to='User', on_delete=models.CASCADE)
views.py
from .serializer import UserSerializer
from .models import User, UserToken
import uuid
from django.contrib.auth.hashers import make_password
class UserView(ModelViewSet):
queryset = User
serializer_class = UserSerializer
@action(methods=['POST'], detail=False)
def login(self, request):
ser = self.get_serializer(data=request.data)
if ser.is_valid():
username = ser.data.get('username')
password = ser.data.get('password')
user = User.objects.filter(username=username, password=password).first()
if user:
# 生成唯一随机token
token = uuid.uuid4()
# 用户登陆过就更新没登录就新增UserToken表
UserToken.objects.update_or_create(defaults={'token': token}, user=user)
return Response({'code': 100, 'msg': '登陆成功'})
return Response({'code': 101, 'msg': '用户名或密码错误'})
return Response(ser.errors)
serializer.py
from .models import User
from rest_framework import serializers
class UserSerializer(serializers.ModelSerializer):
class Meta:
model = User
fields = '__all__'
urls.y
from django.contrib import admin
from django.urls import path
from rest_framework.routers import DefaultRouter
from app01 import views
router = DefaultRouter()
router.register('user', views.UserView, 'user')
urlpatterns = [
path('admin/', admin.site.urls),
]
urlpatterns.extend(router.urls)
认证
访问接口时, 需要登录后才能访问
编写认证类
1. 新建一个认证py文件, 写一个认证类, 继承BaseAuthentication
2.规定通过路由后缀传递token值, 【如果token值可以查询到, 说明可以登录】
3. 重写authenticate方法
4. 验证成功返回两个值【当前登录用户和token]
5. 验证失败则抛出AuthenticationFailed异常
6. 只要验证成功,后续requestuser就是当前登陆用户
userauth.py
from rest_framework.authentication import BaseAuthentication
from .models import UserToken
from rest_framework.exceptions import AuthenticationFailed
class UserAuth(BaseAuthentication):
def authenticate(self, request):
token = request.GET.get('token')
token_obj = UserToken.objects.filter(token=token).first()
if token_obj:
return token_obj.user, token
else:
raise AuthenticationFailed('没有登陆')
全局使用
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': ['app01.userauth.UserAuth']
}
局部使用
class UserView(ModelViewSet):
queryset = User.objects
serializer_class = UserSerializer
authentication_classes = [UserAuth]
局部禁用将authentication_classes设置为空即可。
内置的认证类
-BasicAuthentication
-RemoteUserAuthentication
-SessionAuthentication:session认证,建议自己写
-如果前端带着cookie过来,经过session的中间件,如果登录了,在request.user中就有当前登录用户
-drf没有限制是否登录
-加了这个认证,如果没有登录,就不允许往后访问了
-TokenAuthentication:jwt认证,建议自己写
-建议自己写
on_delete相关
当一个由ForeignKey引用的对象被删除时, django将模拟on_delete参数所指定的SQL约束的行为。 例如: 有一个可为空的ForeignKey,并且你希望当被引用的对象被删除时他被设置为空
class Book(models.Model):
title = models.CharField(max_length=32)
price = models.CharField(max_length=32)
publish = models.ForeignKey(to='Publish', on_delete=models.SET_NULL, null=True)
1. models.CASCADE
级联操作, 当主表中被连接的一条数据删除时,从表中所有与之关联的数据同时被删除
2. models.SET_NULL
当主表中的一行数据删除时, 从表中与之关联的数据的相关字段设置为null, 此时注意定义外键时, 这个字段必须可以允许为空
3. models.PROTECT
当主表中的一行数据删除时,由于从表中相关字段是受保护的外键 , 所以都不允许删除
4. models.SET_DEFAULT
当主表中的一行数据删除时,从表中所有的关联数据的关联字段设置为默认值, 此时主要定义外键时, 这个外键字段应该有一个默认值
5. models.SET()
【当主表中的一条数据删除时, 从表中所有的关联数据字段设置为SET()中设置的值, 与models.SET_DEFAULT相似, 只不过此时从表中的相关字段不需要设置default参数】
将ForeignKey设置为传递给Set()的值, 如果传入了一个可调配对象,则设置为调用它的结果, 大多数情况下,为了避免在导入models,py时执行查询, 需要传入一个可调用对象
from django.conf import settings
from django.contrib.auth import get_user_model
from django.db import models
def get_sentinel_user():
return get_user_model().objects.get_or_create(username='deleted')[0]
class MyModel(models.Model):
user = models.ForeignKey(
settings.AUTH_USER_MODEL,
on_delete=models.SET(get_sentinel_user),
)
6. models.DO_NOTHING
什么都不做, 一切都看数据库级别的约束, 注意数据库级别的默认约束为RESTRICT , 这个约束与jango中的models.PROTECT相似
7.models.RESTRICT
通过引发RestrictError(django.db.IntegrityError的一个子类)来防止删除被引用的对象, 与PROTECT不同的是, 如果被引用的对象也引用了一个在统一操作中被删除的不同对象, 但通过CASCADE关系,则允许删除被引用的对象。
class Artist(models.Model):
name = models.CharField(max_length=10)
class Album(models.Model):
artist = models.ForeignKey(Artist, on_delete=models.CASCADE)
class Song(models.Model):
artist = models.ForeignKey(Artist, on_delete=models.CASCADE)
album = models.ForeignKey(Album, on_delete=models.RESTRICT)
Artist可以被删除, 即使这意味着删除被Song引用的Album,因为Song也通过级联关系引用Artist本身, 例如
>>> artist_one = Artist.objects.create(name='artist one')
>>> artist_two = Artist.objects.create(name='artist two')
>>> album_one = Album.objects.create(artist=artist_one)
>>> album_two = Album.objects.create(artist=artist_two)
>>> song_one = Song.objects.create(artist=artist_one, album=album_one)
>>> song_two = Song.objects.create(artist=artist_one, album=album_two)
>>> album_one.delete()
# Raises RestrictedError.
>>> artist_two.delete()
# Raises RestrictedError.
>>> artist_one.delete()
(4, {'Song': 2, 'Album': 1, 'Artist': 1})
权限
权限控制可以限制用户对于视图的访问和对于具体数据对象的访问