使用Django rest框架生成自定义令牌
我目前正在为uni项目构建API。我在以自定义方式生成身份验证令牌时遇到问题。让我解释一下:我应该在端点中接收POST请求,并具有以下内容:使用Django rest框架生成自定义令牌,django,django-rest-framework,token,python-3.6,Django,Django Rest Framework,Token,Python 3.6,我目前正在为uni项目构建API。我在以自定义方式生成身份验证令牌时遇到问题。让我解释一下:我应该在端点中接收POST请求,并具有以下内容: { "university_id": 1, "coords":{ "latitude": 0.0, "longitude": 0.0 } } 其思想是,给定大学id和坐标,后端将对其进行验证(检查坐标是否在有效区域内),然后返回如下标记: { "token": asdfsagag23214,
{
"university_id": 1,
"coords":{
"latitude": 0.0,
"longitude": 0.0
}
}
其思想是,给定大学id
和坐标
,后端将对其进行验证(检查坐标是否在有效区域内),然后返回如下标记:
{
"token": asdfsagag23214,
}
如您所见,没有涉及登录凭据(也没有客户端应用程序的用户模型),因此我猜测我需要创建一个自定义令牌。我查阅了Django REST框架文档,为我的令牌模型找到了类似的内容:
class AuthToken(models.Model):
key = models.CharField(verbose_name='Key', max_length=40, primary_key=True)
created = models.DateTimeField(
verbose_name='Creation date', auto_now_add=True)
class Meta:
verbose_name = 'Token'
verbose_name_plural = 'Tokens'
def save(self, *args, **kwargs):
if not self.key:
self.key = self.generate_key()
return super().save(*args, **kwargs)
def generate_key(self):
return binascii.hexlify(os.urandom(20)).decode()
def __str__(self):
return self.key
然后,它是序列化程序:
class AuthTokenSerializer(serializers.Serializer):
class Meta:
model = AuthToken
fields = ('key', 'created', )
def to_internal_value(self, data):
university = data.get('university')
coords = data.get('coords')
if not university:
raise serializers.ValidationError({
'university': 'This field is required.'
})
if not coords:
raise serializers.ValidationError({
'coords': 'This field is required.'
})
# coordinate validation goes here
return {
'university': int(university),
'coords': coords
}
def create(self, validated_data):
return AuthToken.objects.create(**validated_data)
最后,视图.py
:
@api_view(['POST'])
def generate_token(request):
if request.method == 'POST':
serializer = AuthTokenSerializer(data=request.data)
if serializer.is_valid():
serializer.save()
return Response(serializer.data, status=status.HTTP_201_CREATED)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
我不确定我遗漏了什么,但我无法确定我需要做什么才能使它正常工作。现在我正在使用swagger来测试它,它在任何方式、形状或形式下都不起作用,没有参数可输入,甚至使用cURL via terminal似乎也不能给我预期的结果
对于记录,我使用的是Django 2.1
和Django Rest框架3.8.2
我将非常感谢任何帮助,以及对这段代码的进一步评论(毕竟我还在学习)。我猜我遗漏了一些方法,但不确定在哪里。我将一步一步地进行 首先,您需要为coords定义一个序列化程序,因为获取和验证用户输入的标准方法是通过序列化程序。因此:
class Coordinates(serializers.Serializer):
latitude = serializers.FloatField(min_value=-90, max_value=90)
longitude = serializers.FloatField(min_value=-180, max_value=180)
因此,我想,为字段设置最小值和最大值可以进行足够的验证。如果您想对该字段进行更多验证,可以使用
其次,将serializer.ModelSerializer
用于AuthTokenSerializer
,然后将此字段添加到其中:
coords = Coordinates(write_only=True)
并使其只写
您还可以使用以下方法获得大学:
university = serializers.PrimaryKeyRelatedField(queryset=University.objects.all(), write_only=True)
到目前为止,您的序列化程序应该如下所示:
class AuthTokenSerializer(serializers.ModelSerializer):
university = serializers.PrimaryKeyRelatedField(queryset=University.objects.all(), write_only=True)
coords = Coordinates(write_only=True)
class Meta:
model = AuthToken
fields = ('key', 'created', 'coords', 'university')
在下一步中,您应该使键
和创建的
只读,因为您不想从用户输入中获取它们的值,您只想在创建AuthToken
实例后向用户显示它们的值。因此,将它们添加到Meta类中的只读字段中
在下一步中,您应该重写序列化程序validate
方法,并基于多个字段进行验证(
检查坐标是否在有效区域内
)
最后,您将看到序列化程序如下所示:
class AuthTokenSerializer(serializers.ModelSerializer):
university = serializers.PrimaryKeyRelatedField(queryset=University.objects.all(), write_only=True)
coords = Coordinates(write_only=True)
class Meta:
model = AuthToken
fields = ('key', 'created', 'coords', 'university')
read_only_fields = ('key', 'created')
def validate(self, attrs):
### the the validation here, something like this
### you can access the selected university instance: attrs['university']
if attrs['coords']['latitude'] < attrs['university']:# blah blah blah, anyway you want to validate
raise serializers.ValidationError({'coords': ['invalid coords']})
return super().validate(attrs)
def create(self, validated_data):
### your AuthToken does not have this field, you should pop university and coords
### out before createing an instance of Authtoken
validated_data.pop('university')
validated_data.pop('coords')
return super().create(validated_data)
类AuthTokenSerializer(serializers.ModelSerializer):
university=serializers.PrimaryKeyRelatedField(queryset=university.objects.all(),write_only=True)
坐标=坐标(仅写=真)
类元:
model=AuthToken
字段=('key','created','coords','university')
只读字段=('key','created')
def验证(自身、属性):
###这里的验证是这样的
###您可以访问所选大学实例:attrs['university']
如果attrs['coords']['latitude']
这就成功了。我试图准确地找到如何插入所需的验证,但我不知道我需要为坐标创建一个单独的序列化程序。谢谢。
def create(self, validated_data):
### your AuthToken does not have this field, you should pop university and coords
### out before creating an instance of Authtoken
validated_data.pop('university')
validated_data.pop('coords')
return super().create(validated_data)
class AuthTokenSerializer(serializers.ModelSerializer):
university = serializers.PrimaryKeyRelatedField(queryset=University.objects.all(), write_only=True)
coords = Coordinates(write_only=True)
class Meta:
model = AuthToken
fields = ('key', 'created', 'coords', 'university')
read_only_fields = ('key', 'created')
def validate(self, attrs):
### the the validation here, something like this
### you can access the selected university instance: attrs['university']
if attrs['coords']['latitude'] < attrs['university']:# blah blah blah, anyway you want to validate
raise serializers.ValidationError({'coords': ['invalid coords']})
return super().validate(attrs)
def create(self, validated_data):
### your AuthToken does not have this field, you should pop university and coords
### out before createing an instance of Authtoken
validated_data.pop('university')
validated_data.pop('coords')
return super().create(validated_data)