Add a friend system on django

岁酱吖の 提交于 2020-05-26 09:09:25

问题


I have been trying to add friend system in which the user can add and remove friends (other users), after finishing with the code, I found an error that when the logedin user tries to add a friend from other user's profile, the add friend button redirects to the logedin user profile making it imposible to add a new friend, it can just add himself as a friend. I personally think the error is on the views.py profile view.

views.py (profile shows user's profile and change_friend is the one that adds and removes frinds)

    def profile(request, username=None):
        friend = Friend.objects.filter(current_user=request.user).first()
        friends = []
        if friend:   
          friends = friend.users.all()
        if username:
          post_owner = get_object_or_404(User, username=username)
          user_posts=Post.objects.filter(user_id=post_owner)
        else:
          post_owner = request.user
          user_posts=Post.objects.filter(user=request.user)
        args1 = {
            'post_owner': post_owner,
            'user_posts': user_posts,
            'friends': friends,
        }
        return render(request, 'profile.html', args1)

    def change_friends(request, operation, pk):
        friend = User.objects.get(pk=pk)
        if operation == 'add':
          Friend.make_friend(request.user, friend)
        elif operation == 'remove':
          Friend.lose_friend(request.user, friend)
        return redirect('profile')

models.py

    class Friend(models.Model):
        users = models.ManyToManyField(User, default='users', blank=True, related_name='users')
        current_user = models.ForeignKey(User, related_name='owner', on_delete=models.CASCADE, null=True)

        @classmethod
        def make_friend(cls, current_user, new_friend):
            friend, created = cls.objects.get_or_create(
                current_user=current_user
            )
            friend.users.add(new_friend)

        @classmethod
        def lose_friend(cls, current_user, new_friend):
            friend, created = cls.objects.get_or_create(
                current_user=current_user
            )
            friend.users.remove(new_friend)

profile.html

    <div class="media">
      <div class="media-body">
        <h2 class="account-heading">{{ post_owner.username }}</h2>
        <p class="text-secondary">{{ post_owner.email }}</p>
        {% if not user in friends %}
          <a href="{% url 'change_friends' operation='add' pk=user.pk %}">
            <button type="button">add Friend</button>
          </a>
        {% endif %}
      </div>
    </div>
    <div>
      <h2>Friends</h2>
      {% for friend in friends %}
        <p>{{ friend.username }}</p>
        <a href="{% url 'change_friends' operation='remove' pk=friend.pk %}">
          <button type="button">Remove Friend</button>
        </a>
      {% endfor %}
    </div>

urls.py

    urlpatterns = [
        path('profile/<str:username>/', views.profile, name='profile_pk'),
        url(r'^connect/(?P<operation>.+)/(?P<pk>\d+)/$', views.change_friends, name='change_friends'),
    ]

回答1:


The problem is that you're passing the request.user object to the change_friends view, through the user object. By default user == request.user when used in a template.

Just change that line that you have in profile.html with:

<a href="{% url 'change_friends' operation='add' pk=post_owner.pk %}">
    <button type="button">add Friend</button>
</a>

Now, I note that you're redirecting the user to the profile view once they add a new friend, and that's not what you want. That's happening because when you're calling the redirect() function in your change_friends view, you are not passing any parameter to the profile view. You defined the username should be None by default and then you're saying that if not username then post_owner should be request.user

How to change this? Well, just pass the desired username when calling redirect as a keyword argument. Something as follows:

return redirect('profile', username=friend.username)



回答2:


In your view, friends address to already added friends, you want to get the users are eligible to add as friend to request.user object. To achieve this,

In your profile view:

def profile(request, username=None):
    friend = Friend.objects.filter(current_user=request.user).first()
    friends = []
    # In case of friend is None, I send all users except request user, to be able to add on html template.
    friends_to_add = User.objects.exclude(id=request.user.id)
    if friend:   
        friends = friend.users.all()
        # here we have a valid friend (who is the user request has)
        # so I don't want to send users to template who are already friend of request user.
        friends_to_add = friends_to_add.exclude(id__in=friend.users.values_list("id"))
    if username:
        post_owner = get_object_or_404(User, username=username)
        user_posts=Post.objects.filter(user_id=post_owner)
    else:
        post_owner = request.user
        user_posts=Post.objects.filter(user=request.user)
    args1 = {
        'post_owner': post_owner,
        'user_posts': user_posts,
        'friends': friends,
        'friends_to_add': friends_to_add,
    }
    return render(request, 'profile.html', args1)

In your template file, you can use them as:

<div class="media">
     <div class="media-body">
        <h2 class="account-heading">{{ post_owner.username }}</h2>
        <p class="text-secondary">{{ post_owner.email }}</p>
        {% for user in friends_to_add %}
            <a href="{% url 'change_friends' operation='add' pk=user.pk %}">
                <button type="button">add Friend</button>
            </a>
        {% endfor %}
    </div>
</div>

I hope this will make sense to you. You can ask me anything you cannot understand above from comments if you need.



来源:https://stackoverflow.com/questions/61831356/add-a-friend-system-on-django

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!