- */www.example.commodels.py
class Like(models.Model):
user = models.ForeignKey(settings.AUTH_USER_MODEL,
related_name='likes',
on_delete=models.CASCADE)
content_type = models.ForeignKey(ContentType, on_delete=models.CASCADE)
object_id = models.PositiveIntegerField()
content_object = GenericForeignKey('content_type', 'object_id')
class Content(models.Model):
"""Контент (фильмы, сериалы, и т.д.)"""
title_ru = models.CharField('Название', max_length=200, blank=True)
title_en = models.CharField('Название на английском', max_length=200, blank=True)
rating = models.FloatField('Оценка', validators=[
MaxValueValidator(10.0),
MinValueValidator(0.0),
], default=0.0)
year = models.PositiveSmallIntegerField('Дата выхода', default=date.today().year, null=True)
kinopoisk_id = models.IntegerField('Кинопоиск id')
is_banned = models.BooleanField('Бан', default=False)
def __str__(self):
return f'{self.title_ru} / {self.title_en}'
class Meta:
ordering = ['-year']
verbose_name = 'Контент'
verbose_name_plural = 'Контент'
- */www.example.comservices.py
from django.contrib.auth import get_user_model
from django.contrib.contenttypes.models import ContentType
User = get_user_model()
def add_like(obj, user):
"""Лайк пользователя"""
obj_type = ContentType.objects.get_for_model(obj)
like, is_created = Like.objects.get_or_create(
content_type=obj_type, object_id=obj.id, user=user)
return like
def remove_like(obj, user):
"""Лайкает `obj`."""
obj_type = ContentType.objects.get_for_model(obj)
Like.objects.filter(
content_type=obj_type, object_id=obj.id, user=user
).delete()
def is_fan(obj, user) -> bool:
"""Удаляет лайк с `obj`."""
if not user.is_authenticated:
return False
obj_type = ContentType.objects.get_for_model(obj)
likes = Like.objects.filter(
content_type=obj_type, object_id=obj.id, user=user)
return likes.exists()
def get_fans(obj):
"""Получает всех пользователей, которые лайкнули `obj`."""
obj_type = ContentType.objects.get_for_model(obj)
return User.objects.filter(
likes__content_type=obj_type, likes__object_id=obj.id)
- */www.example.comserializers.py
from django.contrib.auth import get_user_model
from rest_framework import serializers
from .services import is_fan
User = get_user_model()
class FanSerializer(serializers.ModelSerializer):
class Meta:
model = User
fields = (
'username',
)
class ContentListSerializer(serializers.ModelSerializer):
"""Список контента"""
class Meta:
model = Content
fields = ('title_ru', 'title_en', 'kinopoisk_id', 'rating', 'year')
class ContentDetailSerializer(serializers.ModelSerializer):
"""Информация о контенте"""
is_fan = serializers.SerializerMethodField()
class Meta:
model = Content
exclude = ('is_banned', 'id', 'kinopoisk_id')
def get_is_fan(self, obj) -> bool:
"""Проверяет, лайкнул ли `request.user` твит (`obj`)."""
user = self.context.get('request').user
return is_fan(obj, user)
- */www.example.commixins.py
from rest_framework.decorators import action
from rest_framework.response import Response
from .serializers import FanSerializer
from .services import get_fans, remove_like, add_like
class LikedMixin:
@action(detail=True, methods=['POST'])
def like(self, request, pk=None):
"""Лайкает `obj`."""
obj = self.get_object()
add_like(obj, request.user)
return Response()
@action(detail=True, methods=['POST'])
def unlike(self, request, pk=None):
"""Удаляет лайк с `obj`."""
obj = self.get_object()
remove_like(obj, request.user)
return Response()
@action(detail=True, methods=['GET'])
def fans(self, request, pk=None):
"""Получает всех пользователей, которые лайкнули `obj`."""
obj = self.get_object()
fans = get_fans(obj)
serializer = FanSerializer(fans, many=True)
return Response(serializer.data)
- /查看*
from rest_framework import viewsets
from rest_framework.permissions import IsAuthenticatedOrReadOnly
from .mixins import LikedMixin
from .models import Content
from .serializers import ContentListSerializer, ContentDetailSerializer
class ContentViewSet(LikedMixin, viewsets.ModelViewSet):
"""Вывод деталей контента"""
queryset = Content.objects.filter(is_banned=False)
permission_classes = (IsAuthenticatedOrReadOnly,)
def get_object(self):
kinopoisk_id = self.kwargs.get('pk')
content = get_object_or_404(Content, kinopoisk_id=kinopoisk_id, is_banned=False)
return content
def get_serializer_class(self):
if self.action == 'list':
return ContentListSerializer
elif self.action == 'retrieve':
return ContentDetailSerializer
- /网址*
from django.urls import path
from rest_framework.routers import DefaultRouter
from . import views
router = DefaultRouter()
router.register(r'content', views.ContentViewSet)
urlpatterns = router.urls
- 问题描述:**
当我登录并希望使用链接获取所有内容或特定内容时:
http://127.0.0.1:8000/api/v1/content/?format=json
我成功了,但如果是这样(如果我注销帐户,则不会发生此错误:)
http://127.0.0.1:8000/api/v1/content/
错误:
Request Method: GET
Request URL: http://127.0.0.1:8000/api/v1/content/
Django Version: 4.1.6
Python Version: 3.10.5
Installed Applications:
['django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'django.contrib.postgres',
'debug_toolbar',
'django_elasticsearch_dsl',
'rest_framework',
'django_filters',
'corsheaders',
'rest_framework.authtoken',
'djoser',
'content']
Installed Middleware:
['django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'corsheaders.middleware.CorsMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
'debug_toolbar.middleware.DebugToolbarMiddleware']
Traceback (most recent call last):
File "/Users/nikita/PycharmProjects/MoviePlanetPlatform/venv/lib/python3.10/site-packages/django/core/handlers/exception.py", line 55, in inner
response = get_response(request)
File "/Users/nikita/PycharmProjects/MoviePlanetPlatform/venv/lib/python3.10/site-packages/django/core/handlers/base.py", line 220, in _get_response
response = response.render()
File "/Users/nikita/PycharmProjects/MoviePlanetPlatform/venv/lib/python3.10/site-packages/django/template/response.py", line 114, in render
self.content = self.rendered_content
File "/Users/nikita/PycharmProjects/MoviePlanetPlatform/venv/lib/python3.10/site-packages/rest_framework/response.py", line 70, in rendered_content
ret = renderer.render(self.data, accepted_media_type, context)
File "/Users/nikita/PycharmProjects/MoviePlanetPlatform/venv/lib/python3.10/site-packages/rest_framework/renderers.py", line 723, in render
context = self.get_context(data, accepted_media_type, renderer_context)
File "/Users/nikita/PycharmProjects/MoviePlanetPlatform/venv/lib/python3.10/site-packages/rest_framework/renderers.py", line 654, in get_context
raw_data_post_form = self.get_raw_data_form(data, view, 'POST', request)
File "/Users/nikita/PycharmProjects/MoviePlanetPlatform/venv/lib/python3.10/site-packages/rest_framework/renderers.py", line 553, in get_raw_data_form
serializer = view.get_serializer()
File "/Users/nikita/PycharmProjects/MoviePlanetPlatform/venv/lib/python3.10/site-packages/rest_framework/generics.py", line 110, in get_serializer
return serializer_class(*args, **kwargs)
Exception Type: TypeError at /api/v1/content/
Exception Value: 'NoneType' object is not callable
1条答案
按热度按时间py49o6xq1#
我认为问题就在这里:
您可以将
elif
条件更改为else
以处理所有操作用例,或者在所有条件都不匹配时添加另一个序列化程序。