ゆーじぇいブログ

ゆーじぇいブログ

プログラミングとか色々

[Django]フォロー機能と課題、そして解決へ!

f:id:jyouj:20181124164719j:plain

 フォロー・フォロワー機能を実装しようとしたのだが、うまくいかなかった。しかし、このブログをみてくださった心優しい方がDMで解決策を教えてくれました。

参考:GitHub - benigls/instagram: Instagram clone made with Django framework.
前回
jyouj.hatenablog.com

フォロー・アンフォロー

 まず、models.pyについて。

@python_2_unicode_compatible
class Connection(models.Model):
    follower = models.ForeignKey(User, related_name='follower', on_delete=models.CASCADE)
    following = models.ForeignKey(User, related_name='following', on_delete=models.CASCADE)
    date_created = models.DateTimeField(auto_now_add=True)

    def __str__(self):
        return "{} : {}".format(self.follower.username, self.following.username)

 次に、views.py。

from __future__ import absolute_import

from django.contrib.auth.decorators import login_required
from django.shortcuts import render, redirect
from django.contrib.auth import authenticate, login, logout, update_session_auth_hash
from django.contrib.auth.mixins import LoginRequiredMixin
from django.views.generic import CreateView, TemplateView, DetailView, UpdateView, ListView
from django.urls import reverse_lazy
from django.contrib import messages
from django.http import HttpResponseRedirect, Http404

from .models import User, Connection
from .forms import SignUpForm, LoginForm, ProfileEditForm
from .helpers import get_current_user

class ProfileDetailView(LoginRequiredMixin, DetailView):
    model = User
    template_name = 'users/profile.html'

    slug_field = 'username'
    slug_url_kwarg = 'username'

    def get_context_data(self, **kwargs):
        context = super(ProfileDetailView, self).get_context_data(**kwargs)
        username = self.kwargs['username']
        context['username'] = username
        context['user'] = get_current_user(self.request)
        context['following'] = Connection.objects.filter(follower__username=username).count()
        context['followers'] = Connection.objects.filter(following__username=username).count()

        if username is not context['user'].username:
            result = Connection.objects.filter(follower__username=context['user'].username).filter(following__username=username)
            context['connected'] = True if result else False

        return context

@login_required
def follow_view(request, *args, **kwargs):
    try:
        follower = User.objects.get(username=request.user)
        following = User.objects.get(username=kwargs['username'])
    except User.DoesNotExist:
        messages.warning(request, '{}は存在しません'.format(kwargs['username']))
        return HttpResponseRedirect(reverse_lazy('users:index'))

    if follower == following:
        messages.warning(request, '自分自身はフォローできませんよ')
    else:
        _, created = Connection.objects.get_or_create(follower=follower, following=following)

        if (created):
            messages.success(request, '{}をフォローしました'.format(following.username))
        else:
            messages.warning(request, 'あなたはすでに{}をフォローしています'.format(following.username))

    return HttpResponseRedirect(reverse_lazy('users:profile', kwargs={'username': following.username}))

@login_required
def unfollow_view(request, *args, **kwargs):
    try:
        follower = User.objects.get(username=request.user)
        following = User.objects.get(username=kwargs['username'])
        if follower == following:
            messages.warning(request, '自分自身のフォローを外せません')
        else:
            unfollow = Connection.objects.get(follower=follower, following=following)
            unfollow.delete()
            messages.success(request, 'あなたは{}のフォローを外しました'.format(following.username))
    except User.DoesNotExist:
        messages.warning(request, '{}は存在しません'.format(kwargs['username']))
        return HttpResponseRedirect(reverse_lazy('users:index'))
    except Connection.DoesNotExist:
        messages.warning(request, 'あなたは{0}をフォローしませんでした'.format(following.username))

    return HttpResponseRedirect(reverse_lazy('users:profile', kwargs={'username': following.username}))

 そして、urls.py。

urlpatterns = [
    path('signup', views.SignUpView.as_view(), name='signup'),
    path('login', views.LoginView.as_view(), name='login'),
    path('', views.IndexView.as_view(), name='index'),
    path('logout', views.LogoutView.as_view(), name='logout'),
    path('<slug:username>', views.ProfileDetailView.as_view(), name='profile'),
    path('<slug:username>/edit', views.ProfileUpdateView.as_view(), name='edit'),
    path('<slug:username>/follow', views.follow_view, name='follow'),
    path('<slug:username>/unfollow', views.unfollow_view, name='unfollow'),
]

 templates/users/profile.htmlも編集。

{% extends 'base.html' %}

{% block body %}
<h1>@{{ username }}</h1>
<h3>{{ object.name }}</h3>
<h6>{{ object.about_me }}</h6>

{% if user.username == username %}
<a href="{% url 'users:edit' username %}" class="btn btn-info">プロフィール編集</a>
{% elif connected %}
<a href="{% url 'users:unfollow' username %}" class="btn btn-dark">フォロー解除</a>
{% else %}
<a href="{% url 'users:follow' username %}" class="btn btn-light">フォロー</a>
{% endif %}
{% endblock %}

課題

 実際にいくつかユーザーを作成して、フォローしようとすると、「<ユーザー名>は存在しません」というUser.DoesNotExistが出てしまう。

解決策

 提示してもらった解決策を試してみました。まず、shellを起動してUserが存在するか確かめてみました。

>>>from users.models import User
>>>User.objects.all()

 すると、作成したtestユーザーが出てきました。コードのどこかにミスがあるな、と考えられます。
 またまた、提示してもらった方法を試してみることにしました。views.pyを編集します。

def follow_view(request, *args, **kwargs):
    try:
        follower = User.objects.get(username=request.user.username) # 変更
    # 省略
def unfollow_view(request, *args, **kwargs):
    try:
        follower = User.objects.get(username=request.user.username) # 変更
    # 省略

 すると、思ったように動くことができました。気づかなかったとは、、、。解決策を提示していただきありがとうございました。

 何かありましたら以下に。
 Twitterアカウント:じぇい👨‍💻 (@jyouj__) | Twitter

投げ銭も待ってまーす!-> jyouj__さんの投げ銭ビスケット募集中!