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)
Related
I've menaged to create a form that allow me to save my website user information in the database. Right now I'd like to create a page where the saved info are showed to my user also. Of course I want my user to be able to see only their own information. This is what I came up with until now, it doesn't wotk and unfortunly I'm not getting any error, just a blanck html page aside for the title. How can I solve this? Thank you all!
model.py
class Info(models.Model):
first_name = models.CharField(max_length=120)
last_name = models.CharField(max_length=120)
phone = models.CharField(max_length=10)
views.py
def show(request):
info = Info.objects.all().filter(first_name=request.user)
return render(request, 'profile/show.html', {'info': info})
info.html
<h1> Profile </h1>
</br></br>
{% if user.is_authenticated %}
{% for info in info %}
<li>First Name: {{ info.first_name }}</li>
<li>Last Name: {{ info.last_name }}</li>
<li>Phone Number: {{ info.phone }}</li>
{% endfor %}
{% endif %}
request.user type is User. So when you are passing it to first_name, doesn't seem right
You can do the followings:
def show(request):
user_first_name = request.user.first_name
info = Info.objects.all().filter(first_name=user_first_name)
return render(request, 'profile/show.html', {'info': info})
The filter method apply on queryset in Django return a list not an single object.
You can fix your issue like this :
def show(request):
# You can use id to get a single user like bellow
info_id = Info.objects.get(user_id=request.user.id)
# Or use the `first` method of queryset to retrieve the first element in the list
info_name = Info.objects.all().filter(first_name=request.user.first_name).first()
return render(request, 'profile/show.html', {'info': info})
I'm new to python and django and I need some help, please.
What I'm trying to do is to only show a certain "task" if the user is responsable or author of the "task" in question.
I was trying to do that with a if statement in html template:
{% for task in task_list %}
<h2>title - {{task.title}}</h2>
{% endfor %}
{% endif %}
But does not return what I expected since:
{% for task in task_list %}
<h2>author --- {{task.author}}</h2>
<h2>responsable --- {{task.responsable}}</h2>
{% endfor %}
Returns me the same user... I think the problem is that when I refer user.username it goes to the db and returns a query, and when I user {{task.blablabla}} its a string, I'm right? How I can fix that?
models.py:
title = models.CharField(max_length=50)
content = models.TextField(blank=True)
date_created = models.DateTimeField(auto_now_add=True)
due_date = models.DateTimeField(default=timezone.now)
author = models.ForeignKey(User, on_delete=models.CASCADE, default=User)
responsable = models.ForeignKey(User, on_delete=models.CASCADE, related_name="author", default=User)
STATUS_CHOICES = [('D', 'Done'),('P','Doing'),('N','Not done')]
Status = models.CharField(max_length=1,choices=STATUS_CHOICES, default='N')
IMPORTANCE_CHOICES = [('H', 'High'),('M','Medium'),('L','Low')]
importance = models.CharField(max_length=1,choices=IMPORTANCE_CHOICES, default='M')
DEPARTAMENT_CHOICES = [('D', 'Dev'),('M','Marketing'),('H','Human Resources'),('L','Legal'),('F','Financial'),('O','Others')]
departament = models.CharField(max_length=1,choices=DEPARTAMENT_CHOICES, default='M')
def __str__(self):
return self.title
views.py
def dashboard_taskapp(request):
task = Task.objects.all()
context = {
"task_list": task,
}
return render(request, "task_app/task_dashboard.html", context)
Thanks in advance and kind regards,
So the cleaner and safer solution here is to use Class Based Views (CBV). There is a generic CBV specially created for displaying lists of objects - ListView. To achieve exactly what you did the code would present as follows:
from django.views.generic.list import ListView
class DashboardTaskAppView(ListView):
template_name = "task_app/task_dashboard.html"
# we override this method to
# get the queryset of objects we want to display
# rest of the work will be taken care of by "djnago"
def get_queryset(self):
usr = request.user
return Task.objects.filter(Q(author=usr) | Q(responsible=usr) | Q(public=True))
Now to get the wanted result in template we simply invoke it like this
{% for task in object_list %}
<h2>title - {{task.title}}</h2>
{% endfor %}
when using CBV remember to user path in urls like this
path('your_url/', DashboardTaskAppView.as_view(), name='your_name'),
Please read the docs to discover full Django generic views potential it really speeds up your job and reformatting it later on takes seconds instead of hours.
I hope this is what you want to achieve. Firstly, modify task queryset so it only shows your chosen person's tasks. (You need to import Q for OR contidion)
from django.db.models import Q
def dashboard_taskapp(request):
usr = request.user
task = Task.objects.filter(Q(author=usr) | Q(responsible=usr))
context = {
"task_list": task,
}
return render(request, "task_app/task_dashboard.html", context)
Then there is no need to limit your template so in the end it will look like this
{% for task in task_list %}
<h2>title - {{task.title}}</h2>
... whatever you wanna show here ...
{% endfor %}
I am new to Django and am working on a very basic social media site as a practice project.
Right now, I am trying to figure out how to filter a QuerySet based on a variable and counting how many items in the QuerySet match the filter.
To demonstrate what I am trying to do, let's say I am looping through all the visible posts (like a Facebook post or something similar), and I am wanting to display the number of comments each post has.
This is how I would go about that:
{% post in all_posts %}
<h1> There are currently {{ HOW DO I FILTER AND COUNT? }} comments on this post</h1>
{% endfor %}
This is what the relevant section of my views.py file looks like:
def index(request):
all_posts = Posts.objects.order_by('-date_published')
all_comments = Comments.objects.order_by('-date_published')
context = {'all_posts': all_posts,
'all_comments': all_comments
}
return render(request, 'social/index.html', context)
The comments link to the posts through the postID variable. So, I know this doesn't work, but ideally I would like to replace my HOW DO I FILTER AND COUNT? part of the template with something like:
{{ all_comments.filter(postID=post).count }}
Is there an easy way to do this in my views.py or in the template itself? The main problem I have is that I do not know how I can pass the post variable in the template to some function that return the count I am looking for.
UPDATE:
Below are my Posts and Comments models:
class Posts(models.Model):
title = models.CharField(max_length=200)
author = models.CharField(max_length=200)
content = models.TextField()
date_published = models.DateTimeField('date posted')
class Comments(models.Model):
postID = models.ForeignKey(Posts, on_delete=models.CASCADE)
commenter = models.CharField(max_length=200)
email = models.EmailField(max_length=200)
content = models.TextField()
date_published = models.DateTimeField('date posted')
You can annotate the Posts model objects with the number of Comments with:
def index(request):
all_posts = Posts.objects.annotate(
ncomments=Count('comments')
).order_by('-date_published')
all_comments = Comments.objects.order_by('-date_published')
context = {
'all_posts': all_posts,
'all_comments': all_comments
}
return render(request, 'social/index.html', context)
In the template you can then render this with:
{% post in all_posts %}
<h1> There are currently {{ post.ncomments }} comments on this post</h1>
{% endfor %}
Note: normally a Django model is given a singular name, so Post instead of Posts.
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 :)
I have a problem when trying to display all the Announce objects from a user.
My problem is : Consider that I am logged in as a user with an id=1. When I go to /users/1/ it displays all my posts. But the problem is when I want to display all the posts from another user with id=2 by going to /users/2/, it still display all my Announce objects, and not the user with the id=2.
models.py
class Announce(models.Model):
owner = models.ForeignKey('auth.User', related_name='announces')
created_date = models.DateTimeField(auto_now_add=True)
body = models.TextField(max_length=1000)
views.py
class UserAnnouncesList(ListView):
model = Announce
template_name = 'myApp/user_announces_list.html'
context_object_name = 'all_announces_by_user'
def get_queryset(self):
return Announce.objects.filter(owner=self.request.user)
urls.py
urlpatterns = [
url(r'users/(?P<pk>[0-9]+)/$', views.UserAnnouncesList.as_view(), name='user_announces_list'),]
user_announces_list.html
{% extends "account/base.html" %}
{% block content %}
{% for announce in all_announces_by_user %}
<h1>{{announce.user.username}}</h1>
<p>{{announce.body}}</p>
{% endfor %}
{% endblock content %}
Do I have to use some kind of like : Announce.objects.get(pk=???) ?
I appreciate your help!
The request.user is the user that is logged in. You need to use the pk that is passed as url. This is stored in the kwargs dictionary of the listview:
class UserAnnouncesList(ListView):
model = Announce
template_name = 'myApp/user_announces_list.html'
context_object_name = 'all_announces_by_user'
def get_queryset(self):
return Announce.objects.filter(owner=self.kwargs['pk'])