Django,Profile matching query does not exist error at profile/1

Question:

Whenever I click on the profiles(links) on the profile_list page, I get the profile doesn’t exist error
it always goes to profiles that do not longer exist in the database.

Models.py:

from django.db import models
from django.contrib.auth.models import User
from django.db.models.signals import post_save
from django.dispatch import receiver

# Create your models here.
class Profile(models.Model):
    user=models.OneToOneField(User,on_delete=models.CASCADE)
    follows=models.ManyToManyField(
        "self",
        related_name="followed_by",
        symmetrical=False,
        blank=True)
    def __str__(self):
        return self.user.username

@receiver(post_save,sender=User)
def create_profile(sender, instance, created, **kwargs):
    if created:
        user_profile=Profile(user=instance)
        user_profile.save()
        user_profile.follows.add(instance.profile)
        user_profile.save()

admin.py:

from django.contrib import admin
from django.contrib.auth.models import Group,User
from .models import Profile


class ProfileInline(admin.StackedInline):
    model=Profile

class UserAdmin(admin.ModelAdmin):
    model=User
    fields=["username"]
    inlines=[ProfileInline]

# Register your models here.
admin.site.unregister(Group)
admin.site.unregister(User)

admin.site.register(User,UserAdmin)


views.py:

from django.urls import reverse
from django.shortcuts import render
from requests import request
from users.models import Profile
from django.http import HttpResponseRedirect

# Create your views here.
def dashboard(request):
    return render(request,"inbox/layout.html")

def feed(request):
    return render(request,"inbox/feed.html")

def outbox(request):
    return render(request,"inbox/outbox.html")

def profile_list(request):
    profiles=Profile.objects.exclude(user=request.user)
    return render(request,"inbox/profile_list.html",{"profiles":profiles})

def profile(request, pk):    
    if not hasattr(request.user, 'profile'):
        missing_profile = Profile(user=request.user)
        missing_profile.save()
   
    profile = Profile.objects.get(pk=pk)
    if request.method == "POST":
        current_user_profile = request.user.profile
        data = request.POST
        action = data.get("follow")
        if action == "follow":
            current_user_profile.follows.add(profile)
        elif action == "unfollow":
            current_user_profile.follows.remove(profile)
        current_user_profile.save()
    return render(request, "inbox/profile.html", {"profile": profile})

profile.html:

<!-- inbox/templates/inbox/profile_list.html -->
{% extends 'inbox/layout.html' %}
{% block content %}
<form method="post">

{% csrf_token %}
<div >

    <p>@{{ profile.user.username|upper }}</p>
    <div class="buttons has-addons">
        {% if profile in user.profile.follows.all %}  
            <button class="button is-success is-static">Follow</button>   
            <button class="button is-danger" name="follow" value="unfollow">  
                Unfollow   
            </button>   
        {% else %} 
            <button class="button is-success" name="follow" value="follow">
                Follow
            </button>
            <button class="button is-danger is-static">Unfollow</button>
        {% endif %}
        </div>
    <p1>following:</p1>
    <ul>

        {% for following in profile.follows.all %}
        
            <li><a href="{% url 'inbox:profile' pk=following.pk %}">{{ following }}</a></li>
        
        {% endfor %}
        
        </ul>
        <p2>followers:</p2>
        <ul>

            {% for follower in profile.followed_by.all %}
            
                <li><a href="{% url 'inbox:profile' pk=follower.pk %}">{{ follower }}</a></li>
            
            {% endfor %}
            
            </ul>
    

</div>

</form>

{% endblock content %}

profile_list.html template:

<!-- inbox/templates/inbox/profile_list.html -->
{% extends 'inbox/layout.html' %}
{% block content %}
<form method="post">

{% csrf_token %}
{% for profile in profiles %}


<div class="column">

    <p>{{ profile.user.username }}</p>

    <p><a href="{% url 'inbox:profile' pk=profile.user.pk %}">@{{ profile.user.username|lower }}</a></p>      
</div>
{% endfor %}
</form>
{% endblock content %}
Asked By: Saruni

||

Answers:

You need to match Profile's pk with profile = Profile.objects.get(pk=pk), currently you mentioned the pk of User model, which matched the given queryset in profile view, so try sending pk of profile in profile_list.html template:

{% for profile in profiles %}
<div class="column">
    <p>{{ profile.user.username }}</p>
    <p><a href="{% url 'profile' pk=profile.pk %}">@{{ profile.user.username|lower }}</a></p>      
</div>
{% endfor %}

Also, it is better to use get_object_or_404 instead of get, as it calls get() on a given model manager, but it raises Http404 instead of the model’s DoesNotExist exception.

So, views.py:

def profile(request, pk):
    if not hasattr(request.user, 'profile'):
        missing_profile = Profile(user=request.user)
        missing_profile.save()
    profile = get_object_or_404(Profile, pk=pk)
    if request.method == "POST":
        current_user_profile = request.user.profile
        data = request.POST
        action = data.get("follow")
        if action == "follow":
            current_user_profile.follows.add(profile)
        elif action == "unfollow":
            current_user_profile.follows.remove(profile)
        current_user_profile.save()
    return render(request, "home/profile.html", {"profile": profile})

Now, if the profile does not exist, it will show no Profile matches the given query.

Answered By: Sunderam Dubey