Getting error in Django: matching query does not exist - python

So basically, I have a Friend model, and in the model is all the code, and then in the views, I have some code for friends as well, and I am getting this error
matching query does not exist.
I have tried all the solutions I have found online, however none have worked yet, so I came here to try and find the answer. This is using the latest version of Django.
Relevant models.py
class Friend(models.Model):
users = models.ManyToManyField(User)
current_user = models.ForeignKey(User,related_name='owner',null=True,on_delete=models.CASCADE)
#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)
This is the relevant views.py
Sorry if it's a bit long
class PostListView(SelectRelatedMixin,TagMixin,generic.ListView):
model = Post
template_name = 'mainapp/post_list.html'
selected_related = ("user","group")
queryset = models.Post.objects.all()
def get(self,request):
users = User.objects.exclude(id=request.user.id)
friend = Friend.objects.get(current_user=request.user)
friends = friend.users.all()
context = {
'users':users,'friends':friends
}
return render(request, self.template_name, context)
def get_context_data(self,**kwargs):
context = super(PostListView,self).get_context_data(**kwargs)
context['user_groups'] = Group.objects.filter(members__in=[self.request.user.id])
context['all_groups'] = Group.objects.all()
return context
def get_queryset(self):
return Post.objects.filter(published_date__lte=timezone.now()).order_by('-published_date')
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('mainapp:post_list')
So the actual error is happening in the get() method with the friend = Friend.objects.get(current_user=request.user) line.
Here is the urls.py file.
#post list url
path('posts/',views.PostListView.as_view(),name='post_list'),
# connect url
path('connect/<operation>/<pk>',views.change_friends,name='change_friends'),
And here is the relevant code in post_list.html
<p>People to connect with</p>
{% for user in users %}
<a href="#">
<p>{{ user.username }}</p>
</a>
{% if request.user.is_authenticated %}
<p>Friends</p>
{% for friend in friends %}
<a href="#">
<p>{{ friend.username }}</p>
</a>
{% endif %}
I am not sure why I am getting this error, and all the solutions online have not solved this.
I am expecting no errors to occur, and for the users and friends to work properly, however this is not the case and I am recieving this error.
Thank you for any help you are able to give :)

Related

ManyToMany fields are not showing in if statement in template

I am building a BlogApp and I am stuck on a Problem.
What i am trying to do :-
I am trying to use if statement in template of two many fields BUT if statement is not working correctly.
models.py
class Profile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE,default='',unique=True)
friends = models.ManyToManyField("Profile",blank=True)
class Post(models.Model):
post_owner = models.ForeignKey(User,default='',null=True,on_delete = models.CASCADE)
viewers = models.ManyToManyField(settings.AUTH_USER_MODEL,related_name='viewed_posts',editable=False)
views.py
def detail_view(request,pk,slug):
post = get_object_or_404(Post,pk=pk)
friend = request.user.profile.friends.all()
saw = post.viewers.all()
context = {'friend':friend,'saw':saw}
template.html
{% if request.user.profile.friends.all in post.viewers.all %}
"SHOWING SOME TEXT"
{% endif %}
I am trying to show if request.user friends are in post viewers then show some text.
When i print {{ request.user.profile.friends.all }} it show friends of request.user, It works correctly.
AND when i print {{ post.viewers.all }} then it correctly shows the post viewers (users).
When i try to print some text after combine both in if statement then it doesn't showing anything.
I have no idea where is the Mistake.
Any help would be Appreciated.
Thank You in Advance.
You can filter in the view:
def detail_view(request,pk,slug):
post = get_object_or_404(Post,pk=pk)
friend = request.user.profile.friends.all()
saw = post.viewers.all()
seen_friends = post.viewers.filter(
id__in=friend.values_list("user_id")
).exists()
context = {
'friend':friend,'saw':saw,
'seen_friends':seen_friends
}
in template.html:
{% if seen_friends %}
"SHOWING SOME TEXT"
{% endif %}
The problem is in this line
{% if request.user.profile.friends.all in post.viewers.all %}
Update:
The template has an access to request.user object, but not to the profile object. You are trying to apply Django ORM methods in the template, it is not going to work.
def detail_view(request,pk,slug):
# some code
profile = Profile.objects.get(user=request.user)
context = {'profile':profile}
# more code
return render(request, template_file, context)

Creating a list showing how many posts every user has posted on site

I'm working (or better I'm learning) in django, i want to create an html page with a list that shows how many posts every user has published so far.
in views.py i set:
#user_passes_test(lambda u: u.is_staff) #<-Because I want that only admin will see this
def num_post(request):
num_post = Post.objects.filter(author=request.user).count()
return render(request, 'api/post_numbers.html', {'num_post' : num_post})
and in post_numbers.html i set:
{{user.username}} : {{ num_post }}
but i can only obtain the name and the post number of the current user...
how can i solve this?
Thank you in advance!
request.user represents your current user which is authenticated and in case the session is not authenticated it will be AnonymousUser.
num_post = Post.objects.filter(author=request.user).count()
So when you query this it will show number of posts of current user only.
from django.db.models import Count
#user_passes_test(lambda u: u.is_staff) #<-Because I want that only admin will see this
def num_post(request):
num_post = dict(Post.objects.values_list('author__username').annotate(Count('id')))
return render(request, 'api/post_numbers.html', {'num_post' : num_post})
template
{% for username, num in num_post.items %}
<li>{{ username }} : {{ num }}</li>
{% endfor %}
views.py : User being your user model.
#user_passes_test(lambda u: u.is_staff)
def num_post(request):
users = User.objects.all()
for user in users:
user.num_post = Post.objects.filter(author=user).count()
context = {'users':users}
return render(request, 'api/post_numbers.html', context=context)
template
{% for user in users %}
{{user.username}} : {{ user.num_post }}
{%endfor%}

Return usernames mentioned in post as profile links to those users inside the post

Hey guys I'm trying to get my code to check for a user mentioned in a post with #username that is in the database and return that users profile link as the #username. I am currently able to get the users in the backend with the tagged_users variable in my views. It store the users mentioned but how do I access that in the template so that it gives me the link to those users profiles? so far my code is this in the template
{% if post.post|slice:":1" == '#' %}
<a href="{% url 'profile_with_pk' pk=user.username %}">
{{ post.post }}
</a>
{% else %}
{{ post.post }}
{% endif %}
this returns the entire post as a link but does not return the actual user mentioned in the post instead it makes a link to the current user logged in
This is my code that brings back the users mentioned in the tagged_users list correctly I want to access this in the template as a link to those users profiles in the post.
def post(self, request, pk=None):
if pk:
user = User.objects.get(pk=pk)
else:
user = request.user
form = HomeForm(request.POST)
users = User.objects.all()
if form.is_valid():
post = form.save(commit=False)
post.user = request.user
post.save()
tagUsers = re.findall(r"#+(\w+)", post.post)
tagged_users = list()
for username in tagUsers:
user = User.objects.get(username=username)
tagged_users.append(user)
print(tagged_users)
text = form.cleaned_data['post']
form = HomeForm()
tag = tagged_users
return redirect('home')
context = {'form': form, 'text': text, 'users':users, 'user': user, 'tag':tag, 'tagUsers':tagUsers }
return render(request, self.template_name, context)
There are multiple problems. Let's start from this one:
<a href="{% url 'profile_with_pk' pk=user.username %}">
{{ post.post }}
</a>
The whole post is wrapped in the link. I think you want to make a link to the post author, right? Then (with only guessing your model schema that you didn't posted), you need something like this:
# iteration through posts somewhere here
user.username
{{ post.post }}
Next, is that if you have tagged users, you need to somehow put them into the template in your posts. Depending on how you wish to put a link to mentionned users this may be something like:
# iteration through posts somewhere here
user.username
{{ post.post }}
Mentions: {% for tagged_user in tagUsers %} {{ tagged_user.username }} {% endfor %}
Or maybe you want to insert links directly inside post text? Then you need to construct a post structure before passing it to template (example snipped; will rather need improvements):
from django.utils.html import mark_safe
def post(self, request, pk=None):
...
post_text = post.post
tagUsers = re.findall(r"#+(\w+)", post.post)
tagged_users = list()
for username in tagUsers:
user = User.objects.get(username=username)
for match in re.finditer(username, post_text):
start = match.start()
end = match.end()
profile_link = reverse('profile_with_pk', kwargs={'pk': user.id})
post_text[start:end] = mark_safe(f'username')
...
# return post_text to template context and use in the same way as used post

How to return multiple items in a get_queryset function in Django?

So I have a web app where the user can enter their information, and eventually I want to display all of it, but at the moment this code right here
class UserPostListView(ListView):
model = Post
template_name = 'mainapp/user_posts.html'
context_object_name = 'posts'
def get_queryset(self):
user = get_object_or_404(User,username=self.kwargs.get('username'))
first_name = get_object_or_404(User,first_name=self.kwargs.get('first_name'))
return Post.objects.filter(author=user).order_by('-published_date')
It gives me an error, and it says User not found.
I have tried add this to the end of the return statement
.order_by('-published_date'),first_name
However this did not work.
This is the relevant urls.py file responsible for the user posts
path('user/<str:username>', UserPostListView.as_view(), name='user-posts'),
This is the UserProfileInfo model
class UserProfileInfo(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
first_name = models.CharField(max_length=50,blank=True,null=True)
last_name = models.CharField(max_length=50,blank=True,null=True)
description = models.CharField(max_length=150)
image = ProcessedImageField(upload_to='profile_pics',
processors=[ResizeToFill(150, 150)],
default='default.jpg',
format='JPEG',
options={'quality': 60})
joined_date = models.DateTimeField(blank=True,null=True,default=timezone.now)
verified = models.BooleanField( default=False)
def __str__(self):
return f'{self.user.username} Profile'
def save(self, *args, **kwargs):
super().save(*args, **kwargs)
And here is the relevant bit of the user-posts.html
<div class="sidebar">
<p class="active" href="#">{{ view.kwargs.username }}</p>
<button class="commentbtn"><a class="aclass" href="#">Connect with {{ view.kwargs.username }}</a></button>
<p>{{ view.kwargs.first_name }}</p>
<p>Lorem</p>
</div>
I want to be able to display the first name of the person in the ```{{ view.kwargs.first_name }}, however everything I have tried has failed to work
I expected no errors to occur and for this to work, however this is not the case. Is it possible to have 2 get_queryset methods, or is there something I can do in the current one to achieve my goal of displaying the information of the user
Thanks for any help you can give :)
How about this?
def get_queryset(self):
qs = super().get_queryset() #this is the same as Post.objects.all()
user = self.request.user
return qs.objects.filter(author=user).order_by('-published_date')
Now you can access this query using object_list on your template, but since you changed it's name with context_object_name='posts', use posts instead:
{% for post in posts %}
<h1>{{ post.first_name }}</h1>
...
{% endfor %}
But it looks like the Post model isn't going to have a first_name column?
You might be better off using the request.user object here as well:
<h1>{{ request.user.first_name }}</h1>
<h2>{{ request.user.username }}</h2>

Authenticate list in Django Python

I'm creating an app that allows Users to create personal goals and then allow them to view those goals once created. When the goal is created it goes into my database and is put onto a list page that users are able to view. The problem is that all users are able to view these goals, not just their own. Below is my code showing how I am trying to make the lists for the users eyes only:
Models
class Goal(models.Model):
# values that I am storing in my SQLlite DB
title = models.CharField(max_length=1000)
body = models.TextField()
created_data = models.DateTimeField(auto_now_add=True, auto_now=False)
updated_data = models.DateTimeField(auto_now_add=False, auto_now=True)
user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
# user = models.OneToOneField(User, on_delete=models.CASCADE)
def __str__(self):
return self.title
# Where I am trying to authenticate the user
def get_queryset(self, *args, **kwargs):
return Goal.objects.all().filter(owner=self.request.user)
Views
def goal_list(request):
goals = Goal.objects.all().order_by('created_data')
return render(request, 'goals/goal_list.html', { 'goals': goals })
#login_required
def goal_create(request, *args):
if request.method == 'POST':
form = forms.CreateGoal(request.POST, request.FILES)
if form.is_valid():
# saving my form
goal_create = form.save(commit=False)
goal_create.user = request.user
goal_create.save()
return redirect('goals:goal_list')
else:
form = forms.CreateGoal()
return render(request, 'goals/goal_create.html', {'form': form})
html
{% block body%}
<div class="container">
<h1>Goals List</h1>
<div class="goals">
{% for goal in goals %}
<div class="goal">
{% these are the values Im displaying on the webpage. %}
<h2>{{ goal.title }}</h2>
<p>{{ goal.goal.title }}</p>
<p>{{ goal.body }}</p>
<p>{{ goal.created_data }}</p>
{# <p>{{ goal.user }}</p>#}
</div>
{% endfor %}
</div>
{% endblock %}
You can't put your get_queryset method in the model, because you don't have access to the request there.
Use the login_required decorator so that only logged-in users can access the view. Then you can filter the queryset using request.user.
from django.contrib.auth.decorators import login_required
#login_required
def goal_list(request):
goals = Goal.objects.filter(user=request.user).order_by('created_data')
return render(request, 'goals/goal_list.html', {'goals': goals })

Categories