Как использовать фильтр с помощью ContentType, чтобы проверить, присутствует ли экземпляр модели или нет - PullRequest
0 голосов
/ 05 октября 2019

Я пытаюсь реализовать подобную функциональность на основе этого . Я хочу ограничить пользователя, чтобы попасть как на событие только один раз. Но я получаю следующую ошибку. Я добавил полную информацию об ошибке внизу

Exception Type: AttributeError at /api/event/likes/create/
Exception Value: 'str' object has no attribute '_meta'

models.py

class ThumbsUpManager(models.Manager):

    def create_by_model_type(self, model_type, slug, content, user, parent_obj=None):

        model_qs = ContentType.objects.filter(model=model_type)
        if model_qs.exists():
            some_model = model_qs.first().model_class()
            obj_qs = some_model.objects.filter(slug=slug)

            if obj_qs.exists() and obj_qs.count() == 1:
                instance = self.model()
                instance.content = content
                instance.user = user
                instance.content_type = model_qs.first()
                instance.object_id = obj_qs.first().id
                if parent_obj:
                    instance.parent = parent_obj
                instance.save()
                return instance
        return None


class Thumbsup(models.Model):
    user = models.ForeignKey(User, on_delete=models.CASCADE)
    content_type = models.ForeignKey(ContentType, on_delete=models.CASCADE)
    object_id = models.PositiveIntegerField()
    content_object = GenericForeignKey('content_type', 'object_id')
    parent = models.ForeignKey("self", null=True, blank=True, on_delete=models.CASCADE)
    content = models.BooleanField(default=False)
    timestamp = models.DateTimeField(auto_now_add=True)
    approved = models.BooleanField(default=True)

    objects = ThumbsUpManager()

    class Meta:
        ordering = ['-timestamp']


    def __str__(self):
        return str(self.user.username)


    @property
    def is_parent(self):
        if self.parent is not None:
            return False
        return True

urls.py

urlpatterns = [
    path('create/', ThumbsUpCreateAPIView.as_view(), name='create'),
]

view.py

class ThumbsUpCreateAPIView(CreateAPIView):
    queryset = Thumbsup.objects.all()
    permission_classes = [IsAuthenticated, ]

    def get_serializer_class(self):
        model_type = self.request.GET.get("type")

        slug = self.request.GET.get("slug")
        obj_qs = Thumbsup.objects.all()
        print(obj_qs)
        parent_id = self.request.GET.get("parent_id", None)
        return create_thumbs_up_serializer(
                model_type=model_type,
                slug=slug,
                parent_id=parent_id,
                user=self.request.user
                )

serializers.py

def create_thumbs_up_serializer(model_type=None, slug=None, parent_id=None, user=None):
    class ThumbsUpCreateSerializer(ModelSerializer):
        class Meta:
            model = Thumbsup
            fields = [
                'id',
                'content',
                'timestamp',
            ]

        def __init__(self, *args, **kwargs):
            self.model_type = model_type
            self.slug = slug
            self.parent_obj = None
            self.user = user
            if parent_id:
                parent_qs = Thumbsup.objects.filter(id=parent_id)
                if parent_qs.exists() and parent_qs.count() == 1:
                    self.parent_obj = parent_qs.first()
            return super(ThumbsUpCreateSerializer, self).__init__(*args, **kwargs)

        def validate(self, data):
            model_type = self.model_type
            slug = self.slug
            model_qs = ContentType.objects.filter(model=model_type)
            if not model_qs.exists() or model_qs.count() != 1:
                raise ValidationError("This is not a valid content type")
            SomeModel = model_qs.first().model_class()
            obj_qs = SomeModel.objects.filter(slug=self.slug)
            if not obj_qs.exists() or obj_qs.count() != 1:
                raise ValidationError("This is not a slug for this content type")

            ######################### ######################### ######################### 
              How do I need to make query here to check if the user already liked the Event or not?
              I tried the following way, but it is not working.


            user_act = Thumbsup.objects.filter(user=self.user, content_type=ContentType.objects.get_for_model(model_type))
            if user_act.exists():
                raise ValidationError("You have already liked the event")


            return data

        def create(self, validated_data):
            content = validated_data.get("content")

            if user:
                main_user = user
            else:
                main_user = User.objects.all().first()

            model_type = self.model_type
            slug = self.slug
            parent_obj = self.parent_obj
            thumbsup = Thumbsup.objects.create_by_model_type(
                model_type, slug, content, main_user,
                parent_obj=parent_obj,
            )
            return thumbsup

    return ThumbsUpCreateSerializer

Трассировка:

File "E:\GIT\blog\backend\venv\lib\site-packages\django\core\handlers\exception.py" in inner
  34.             response = get_response(request)

File "E:\GIT\blog\backend\venv\lib\site-packages\django\core\handlers\base.py" in _get_response
  115.                 response = self.process_exception_by_middleware(e, request)

File "E:\GIT\blog\backend\venv\lib\site-packages\django\core\handlers\base.py" in _get_response
  113.                 response = wrapped_callback(request, *callback_args, **callback_kwargs)

File "E:\GIT\blog\backend\venv\lib\site-packages\django\views\decorators\csrf.py" in wrapped_view
  54.         return view_func(*args, **kwargs)

File "E:\GIT\blog\backend\venv\lib\site-packages\django\views\generic\base.py" in view
  71.             return self.dispatch(request, *args, **kwargs)

File "E:\GIT\blog\backend\venv\lib\site-packages\rest_framework\views.py" in dispatch
  497.             response = self.handle_exception(exc)

File "E:\GIT\blog\backend\venv\lib\site-packages\rest_framework\views.py" in handle_exception
  457.             self.raise_uncaught_exception(exc)

File "E:\GIT\blog\backend\venv\lib\site-packages\rest_framework\views.py" in raise_uncaught_exception
  468.         raise exc

File "E:\GIT\blog\backend\venv\lib\site-packages\rest_framework\views.py" in dispatch
  494.             response = handler(request, *args, **kwargs)

File "E:\GIT\blog\backend\venv\lib\site-packages\rest_framework\generics.py" in post
  190.         return self.create(request, *args, **kwargs)

File "E:\GIT\blog\backend\venv\lib\site-packages\rest_framework\mixins.py" in create
  18.         serializer.is_valid(raise_exception=True)

File "E:\GIT\blog\backend\venv\lib\site-packages\rest_framework\serializers.py" in is_valid
  235.                 self._validated_data = self.run_validation(self.initial_data)

File "E:\GIT\blog\backend\venv\lib\site-packages\rest_framework\serializers.py" in run_validation
  433.             value = self.validate(value)

File "E:\GIT\test-heroku4\thumbsup\api\serializers.py" in validate
  124.             user_act = Thumbsup.objects.filter(user=self.user, content_type=ContentType.objects.get_for_model(model_type))

File "E:\GIT\blog\backend\venv\lib\site-packages\django\contrib\contenttypes\models.py" in get_for_model
  40.         opts = self._get_opts(model, for_concrete_model)

File "E:\GIT\blog\backend\venv\lib\site-packages\django\contrib\contenttypes\models.py" in _get_opts
  27.             model = model._meta.concrete_model

Exception Type: AttributeError at /api/event/likes/create/
Exception Value: 'str' object has no attribute '_meta'

1 Ответ

0 голосов
/ 06 октября 2019

Я проверил экземпляр модели перед сохранением в менеджере моделей, как показано ниже, и он работает нормально. Я не знаю, является ли это правильным способом выполнения задачи или нет (я очень новичок в django. Предложения приветствуются)

def create_by_model_type(self, model_type, slug, content, user, parent_obj=None):
    model_qs = ContentType.objects.filter(model=model_type)
    if model_qs.exists():
        some_model = model_qs.first().model_class()
        obj_qs = some_model.objects.filter(slug=slug)
        if obj_qs.exists() and obj_qs.count() == 1:
            instance = self.model()
            instance.content = content
            instance.user = user
            instance.content_type = model_qs.first()
            instance.object_id = obj_qs.first().id
            if parent_obj:
                instance.parent = parent_obj

            #### Here I have checked for existence before saving the instance ####

            if Thumbsup.objects.filter(object_id=instance.object_id, user=instance.user).exists():
                raise ValidationError({'already_liked': 'You have already liked the item'})
            instance.save()

            return instance
    return None
...