Request.user возвращает AnonymousUser в ModelViewSet, но работает правильно в APIView
Я пытаюсь настроить get_queryset() в моем DocumentViewSet так, чтобы метод GET возвращал все объекты Document, созданные request.user (текущим вошедшим пользователем).
Однако, я застрял на этой ошибке:django.core.exceptions.ValidationError: ['“AnonymousUser” is not a valid UUID.']
Я предполагаю, что это вызвано получением AnonymousUser в качестве моего self.request.user. Странно то, что мои другие APIView, которые работают с request.user, работают безупречно; Единственное различие, которое я смог найти между ними, это тип набора представлений: ModelViewSet против APIView.
Буду благодарен за любую помощь!
document.views
class DocumentViewSet(viewsets.ModelViewSet):
model = Document
serializer_class = DocumentSerializer
list_serializer_class = DocumentListSerializer
permission_classes = (AllowAny,) # for testing, will change later
def get_queryset(self):
user = self.request.user
return Document.objects.filter(user=user)
def perform_create(self, serializer):
print(self.request.user)
serializer.save(user=self.request.user)
document.models
class Document(models.Model):
id = HashidAutoField(primary_key=True)
user = models.ForeignKey(User, on_delete=models.CASCADE, blank=True, null=True)
title = models.CharField(max_length=100, default="Untitled")
template = models.CharField(max_length=100, default="")
editorState = models.JSONField(default=[])
updated = models.DateTimeField(auto_now=True)
created = models.DateTimeField(auto_now_add=True)
def __str__(self):
return self.title
user.models
class User(AbstractUser):
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
username = None
first_name = models.CharField(max_length=100, default="unknown")
last_name = models.CharField(max_length=100, default="unknown")
profile_pic = models.CharField(max_length=200, default="unknown")
email = models.EmailField(unique=True, db_index=True)
secret_key = models.CharField(max_length=255, default=get_random_secret_key)
USERNAME_FIELD = "email"
REQUIRED_FIELDS = []
class Meta:
swappable = "AUTH_USER_MODEL"
users.api & selectors
Это APIView, который возвращает информацию о пользователе, вошедшем в систему в данный момент; он работает безупречно.
# users.api
class UserMeApi(APIView):
def get(self, request, *args, **kwargs):
return Response(user_get_me(user=request.user))
# users.selectors
def user_get_me(*, user: User):
return {
"id": user.id,
"name": user.name,
"email": user.email,
"first_name": user.first_name,
"last_name": user.last_name,
"profile_pic": user.profile_pic,
}
В DocumentViewSet, get_queryset, следующая строка
Document.objects.filter(user=user)
не работает для анонимного пользователя. Когда ни один пользователь не вошел в систему, request.user возвращает пользователя, которого нет в базе данных. Поэтому его id устанавливается в None. Позади сцены используется id для обработки фильтра, и он пытается сравнить uuid с None. Это не может сработать.
Существует множество способов защиты, вот 2 примера:
if request.user.id: ...
if not request.user.is_anonymous: ...
Моя ошибка! Проблема возникла на фронтенде; я забыл включить withCredentials:true в запрос GET от axios.
axios
.get<DocumentList>(
`${process.env.NEXT_PUBLIC_API_URL}/drafts/?format=json`,
{
withCredentials: true, //forgot this part!
}
)
.then(function (response) {
setDrafts(response.data.results);
});