Получение, если за пользователем следует вошедший в систему пользователь, не работает - PullRequest
1 голос
/ 19 января 2020

У меня есть пользовательская система, которая работает хорошо, пока я не пытаюсь получить информацию, если я слежу за пользователем, но она просто не работает. Вот пример кода.

Что не так

В serializers.py пользователя я пытаюсь проверить, следует ли зарегистрированному пользователю текущий пользователь, он проверяет. Я попытался установить один из 3 ответов: True, False или "not following". Я делаю это в пользовательском сериализаторе, поэтому API может отображать некоторые вещи в зависимости от значения.

Несколько замечаний о том, как следовать и отменять подписку в этом приложении

Статус играет Огромная роль здесь, есть три статуса, на данный момент, followed, unfollowed и blocked. Когда пользователь следует, статус устанавливается на followed при создании, при отмене подписки пользователь не удаляется, а вместо этого статус изменяется на unfollowed, он был разработан таким образом, чтобы сохранять больше данных, таких как время после завершения и остальные.

Что происходит, когда я запускаю приведенный ниже код

Когда я запускаю код, он узнает себя при просмотре своего профиля и возвращает соответствующее сообщение, но когда я просматриваю пользователя, я следую, Я получаю response1 . в этом ответе, поскольку я получаю "not following" вместо True / False, это означает, что блок try вышел из строя.

Я также заметил, что если в сериализаторе в get_am_i_following() функция, которую я изменяю filter(slug=user.slug) на filter(pk=user.pk), запускается, но я получаю False (как показано в response2 ниже), когда на самом деле я должен получить True.

models.py
class User(AbstractBaseUser, PermissionsMixin):
    username = None
    email = models.EmailField(max_length=254, unique=True)
    fullname = models.CharField(max_length=250)
    is_staff = models.BooleanField(default=False)
    is_superuser = models.BooleanField(default=False)
    is_active = models.BooleanField(default=True)
    last_login = models.DateTimeField(null=True, blank=True)
    date_joined = models.DateTimeField(auto_now_add=True)
    slug = models.SlugField(max_length=255, unique=True, blank=True)

    USERNAME_FIELD = 'email'
    REQUIRED_FIELDS = ['fullname']

    objects = UserManager()

    def __str__(self):
        return self.email

    def follow_a_user(self, user_to_follow):
        # find user by slug
        try:
            user_to_follow = User.objects.get(slug=user_to_follow)
        except:
            return False, 'User not found'

        if user_to_follow != self:
            try:
                log = FollowLog.objects.get(
                    user=user_to_follow,
                    followed_by=self,
                )
                log.set_as_followed()
                return True, 'Refollow successful'
            except:
                FollowLog.objects.create(
                    user=user_to_follow,
                    followed_by=self,
                    status=FollowStatus.following.value
                )
                return True, 'Follow Successful'
        else:
            return False, 'Cannot follow oneself'

    def unfollow_a_user(self, user_to_unfollow):
        # find user by slug
        try:
            user_to_unfollow = User.objects.get(slug=user_to_unfollow)
        except:
            return False, 'User not found'

        if user_to_unfollow != self:
            try:
                log = FollowLog.objects.get(
                    user=user_to_unfollow,
                    followed_by=self,
                )
                log.set_as_unfollowed()
                return True, 'UnFollow Successful'
            except Exception as e:
                return False, 'User doesnt follow the specified user' if 'exist' in e else e
        else:
            return False, 'Cannot unfollow oneself'


class FollowStatus(enum.Enum):
    following = 'following'
    unfollowed = 'unfollowed'
    blocked = 'blocked'


FOLLOW_STATUS = (
    ('following', 'following'),
    ('unfollowed', 'unfollowed'),
    ('blocked', 'blocked'),
)


class FollowLog(models.Model):
    user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, related_name='followers')
    followed_by = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE,
                                    related_name='following', null=True)
    followed_on = models.DateTimeField(auto_now_add=True)
    status = models.CharField(choices=FOLLOW_STATUS, default=FollowStatus.following.value, max_length=30)
    updated_on = models.DateTimeField(auto_now=True)
    unfollowed_on = models.DateTimeField(null=True)
    blocked_on = models.DateTimeField(null=True)

    def __str__(self):
        return "{} followed by {} ".format(self.user, self.followed_by)

    def set_as_followed(self):
        self.status = FollowStatus.following.value
        self.save()

    def set_as_blocked(self):
        self.status = FollowStatus.blocked.value
        self.blocked_on = timezone.now()
        self.save()

    def set_as_unfollowed(self):
        self.status = FollowStatus.unfollowed.value
        self.unfollowed_on = timezone.now()
        self.save()
serializers.py

Это место, где я пытаюсь заставить волхвов c произойти, где я возвращаю утверждения, если пользователь (вошедший в систему) следует за другим пользователем, мы проверяем его профиль. Мы делаем это с помощью функции get_am_i_following.

class CustomUserDetailsSerializer(serializers.ModelSerializer):
    '''
    a custom serializer for
    the user to view his own data
    '''
    profiles = ProfileSerializer(read_only=True, many=True)
    showcase = ShowcaseSlugSerializer(read_only=True, many=True)
    followers_count = serializers.SerializerMethodField(read_only=True)
    following_count = serializers.SerializerMethodField(read_only=True)
    am_i_following = serializers.SerializerMethodField(read_only=True)

    class Meta:
        model = User
        fields = ('pk','email', 'fullname', 'profiles', 'slug', 'showcase', 'followers_count', 'following_count', 'am_i_following')
        read_only_fields = ('email', 'fullname', 'profiles', 'slug', 'showcase')

    def get_followers_count(self, instance):
        return instance.followers.all().filter(status='following').count()

    def get_following_count(self, instance):
        return instance.following.all().filter(status='following').count()

    def get_am_i_following(self, instance):
        '''
        returns =
            (
                Myself- when the user i am checking if i follow, is myself
                following- when i am following user
                not following- when user isnt following or when not logged in
            )
        '''
        try:
            request = self.context.get("request")
            user = request.user
            if user==instance:
                return 'Myself'
            else:
                return instance.followers.filter(status='following').filter(slug=user.slug).exists()
        except Exception as e:
            print(e)
            return "not following"
views.py
class UserRetriveAPIView(APIView):
    '''
    Gets a particular user in the database using the slug as the lookup
    '''
    serializer_class = CustomUserDetailsSerializer
    permission_classes = [IsAuthenticatedOrReadOnly, IsUserOrReadOnly]

    def get(self, request, slug):
        user = get_object_or_404(User, slug=slug)

        serializer_context = {"request": request}
        serializer = self.serializer_class(user, context=serializer_context)

        return Response(serializer.data, status=status.HTTP_200_OK)
urls.py
path("users/<slug:slug>/", UserRetriveAPIView.as_view(), name="users-detail")

Обычно при выполнении кода, когда filter(slug=user.slug) в функции get_am_i_following дает мне JSON ответ, где он запускает код исключения

response1
{
    "pk": 1,
    "email": "odedeyiopeyemi94@gmail.com",
    "fullname": "Opeyemi David Odedeyi",
    "profiles": [
        {
            "id": 1,
            "skills": [],
            "user": "opeyemi-david-odedeyi-7ug3j0",
            "date_of_birth": null,
            "bio": null,
            "profile_photo": null,
            "sex": null,
            "type_of_body": null,
            "feet": null,
            "inches": null,
            "lives_in": null,
            "updated_on": "2019-12-06T19:31:38.307863+01:00"
        }
    ],
    "slug": "opeyemi-david-odedeyi-7ug3j0",
    "followers_count": 1,
    "following_count": 2,
    "am_i_following": "not following"
}

Но изменение кода, когда filter(slug=user.slug) в функции get_am_i_following дает мне ответ JSON, но на этот раз возвращает false, когда он должен верните true

{
    "pk": 1,
    "email": "odedeyiopeyemi94@gmail.com",
    "fullname": "Opeyemi David Odedeyi",
    "profiles": [
        {
            "id": 1,
            "skills": [],
            "user": "opeyemi-david-odedeyi-7ug3j0",
            "date_of_birth": null,
            "bio": null,
            "profile_photo": null,
            "sex": null,
            "type_of_body": null,
            "feet": null,
            "inches": null,
            "lives_in": null,
            "updated_on": "2019-12-06T19:31:38.307863+01:00"
        }
    ],
    "slug": "opeyemi-david-odedeyi-7ug3j0",
    "followers_count": 1,
    "following_count": 2,
    "am_i_following": false
}

[ОБНОВЛЕНО]

И просто чтобы быть уверенным, что когда я получаю тех же пользователей, подписчиков, я захожу в систему, что является большей причиной, по которой он должен возвращать True

[
    {
        "followed_by": "olajumoke-dehinbu-3707yd"
    }
]

работает exceptions as e дал мне

Cannot resolve keyword 'slug' into field. Choices are: blocked_on, followed_by, followed_by_id, followed_on, id, status, unfollowed_on, updated_on, user, user_id

1 Ответ

2 голосов
/ 20 января 2020
instance.followers.filter(status='following').filter(slug=user.slug).exists()

Есть ваша ошибка. Например, с вашими моделями, если вы позвоните по номеру

instance.followers.filter(status='following')

. Вы получите все модели FollowLog, где в поле user указан пользователь, для которого мы проверяем его профиль. И теперь вы должны проверить, что пользователь (вошел в систему) следует за ним. Но в модели FollowLog следующий пользователь находится в поле followed_by.

Так попробуйте:

instance.followers.filter(status='following').filter(fallowed_by=user).exists()
...