django - 向缺少用户的 Django Rest APIView 发布请求(令牌身份验证)
问题描述
我正在为 Django 中的类似应用程序的 Twitter 创建 API,并且由于我实现了令牌身份验证(rest-auth),因此在创建新推文时遇到了问题:
{
"author": [
"This field is required."
]
}
我试过 CreateAPIView:
class TweetCreateAPIView(CreateAPIView):
serializer_class = TweetModelSerializer
permission_classes = (IsAuthenticated,)
# I've also tried to add the author field mannualy
def perform_create(self, serializer):
serializer.save(author=self.request.user)
但它没有用,所以我创建了自定义发布方法:
class TweetCreateAPIView(APIView):
permission_classes = (IsAuthenticated,)
def post(self, request, format=None):
serializer = TweetModelSerializer(data=request.data)
if serializer.is_valid():
serializer.save(author=request.user)
return Response(serializer.data, status=status.HTTP_201_CREATED)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
但它仍然无法识别创建推文的用户
模型:
class Tweet(models.Model):
retweeted_by = models.ManyToManyField(
TwitterUser, blank=True, related_name='retweets')
commented_tweet = models.ManyToManyField(
'self', related_name='comments', blank=True, symmetrical=False)
author = models.ForeignKey(
TwitterUser, on_delete=models.CASCADE, related_name='tweets')
content = models.CharField(max_length=280)
created_at = models.DateTimeField(auto_now_add=True)
liked_by = models.ManyToManyField(
TwitterUser, blank=True, related_name='likes')
objects = TweetManager()
def __str__(self):
return self.content
def get_comments(self):
comments = Tweet.objects.filter(commented_tweet__pk=self.pk)
return comments
def get_retweets(self):
retweets = TwitterUser.retweets(tweet__id=self.id)
def get_absolute_url(self):
return reverse('tweets:pk', kwargs={'pk': self.pk})
序列化器:
class TweetModelSerializer(serializers.ModelSerializer):
likes_count = serializers.SerializerMethodField()
already_liked = serializers.SerializerMethodField()
def get_likes_count(self, tweet):
return tweet.liked_by.all().count()
def get_already_liked(self, tweet):
user = None
request = self.context.get("request")
if request and hasattr(request, "user"):
user = request.user
if user is not None:
if user in tweet.liked_by.all():
return True
else:
return False
else:
pass
class Meta:
model = Tweet
fields = [
'id',
'author',
'commented_tweet',
'content',
'retweeted_by',
'likes_count',
'already_liked',
'created_at',
]
设置:
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
# 3rd party
'rest_framework',
'rest_framework.authtoken',
'rest_auth',
'django.contrib.sites',
'channels',
'allauth',
'allauth.account',
'rest_auth.registration',
'reset_migrations',
'corsheaders',
]
REST_FRAMEWORK = {
'DEFAULT_PERMISSION_CLASSES': [
'rest_framework.permissions.DjangoModelPermissionsOrAnonReadOnly'
],
'DEFAULT_AUTHENTICATION_CLASSES': (
'rest_framework.authentication.SessionAuthentication',
'rest_framework.authentication.TokenAuthentication',
),
'DEFAULT_PAGINATION_CLASS': 'twitter.paginations.StandardResultsSetPagination',
'TEST_REQUEST_DEFAULT_FORMAT': 'json',
}
身份验证本身工作正常,包括注册,所以我不认为这是令牌的问题,但我不知道当 CreateAPIView 不起作用时错误在哪里。
解决方案
在您的序列化程序中,您author
在字段列表中。由于它是 a ModelSerializer
,因此 drf 正在从模型中获取该字段的详细信息,并且默认情况下在模型中作者是null = False
,因此 drf 将其设为必填字段,因为它不能为空。但是由于您希望作者自动成为发出请求的用户,因此您不需要该字段是可编辑的。因此,使其成为序列化程序中的只读字段,如下所示:
class TweetModelSerializer(serializers.ModelSerializer):
...
class Meta:
model = Tweet
fields = ('id', 'author', 'commented_tweet', 'content', 'retweeted_by',
'likes_count', 'already_liked', 'created_at', )
read_only_fields = ('author', ) # it's read only now, so drf go looking for it in POST data
现在你只需要重写perform_create
方法,不需要改变 post 方法。
如果您需要更多的自定义,比如superuser
可以编辑作者但没有其他人,您可以覆盖__init__
序列化程序的方法并使字段 read_onlyrequest.user
变得有点复杂。
此外,您应该考虑使用tuple
而不是list
forfields
来read_only_fields
获得较小的性能提升。
推荐阅读
- c# - 如何检查字符串是否在特定位置包含 int?
- angular - 获取选择单选Angular 6的默认值
- javascript - ajax url 附加在文档准备好的当前 url 上并给出 302 错误
- mongodb - 与 $in 查询一起使用时的 MongoDB 排序性能
- php - 如何从 Laravel db 获取数据到 googlechart?
- python - 如何在 python 脚本中获取 .txt 形式的命令提示符输出?
- python - 使用美丽的汤从各种标签中提取标题
- sql - 如何根据列类型修改表格单元格?
- javascript - 为什么我们要完成 observable?
- service - 为什么配置示例服务文件没有@Injectable 装饰器?