I can retrieve data by explicitly giving the 'Id' but I want to retrieve it automatically the top 3 'Id' data. How can I do that. please check my code below and help me out
this is models.py
class Post(models.Model):
title = models.CharField(max_length=200, unique=True)
def __str__(self):
return self.title
this is admin.py
class PostAdmin(admin.ModelAdmin):
list_display = ('id','title')
admin.site.register(Post, PostAdmin)
this is views.py
def index(request):
post3 = get_object_or_404(Post, id=3)
post2 = get_object_or_404(Post, id=2)
post1 = get_object_or_404(Post, id=1)
context = {
"post3": post3,
"post2": post2,
"post1": post1,
}
return render(request, 'contents/index.html', context)
as you can see in the above am giving the id number and it works fine but I want it to retrieve the top id automatically
this is my remplate
<h3>{{post3.title}}</h3>
<h3>{{post2.title}}</h3>
<h3>{{post1.title}}</h3>
You can just use slice on queryset (it will automatically add LIMIT to the SQL query) or take objects specified by index:
posts = Post.objects.all()[:3] # 3 first objects
posts = Post.objects.order_by("-id")[:3] # 3 last objects
post = Post.objects.last() # last object
post = Post.objects.order_by("-id")[0] # also last object, but it's better to use `last` in such case
post = Post.objects.order_by("-id")[1] # pre-last object
Pass it to the context:
context = {"posts": posts}
And then you can process this queryset in template:
{% for post in posts %}
<h3>{{ post.title }}</h3>
{% endfor %}
you should query in views for instance posts = Post.objects.all()[0:3] and then in template use for loop
{% for post in posts %}
{{ post.title }}
If you want to create DetailView you can pass post.id via template and add it as parameter in view, then Post = get_object_or_404(id=post_id)
Related
I am trying to create a page on my site (social media type) where the posts would be grouped and displayed by the user that created them.
I tried creating a following context item and then accessing the posts through each of the users in that group but it is not showing any results.
I also tried filtering posts by the users in following. However, it does not show any results. I don't know if I am using the filter function correctly.
This is my View:
class CommunityListView(LoginRequiredMixin, ListView):
model = Post
template_name = 'community/community.html'
context_object_name = 'posts'
ordering = ['-date_added']
def get_context_data(self, **kwargs):
context = super(CommunityListView, self).get_context_data(**kwargs)
active_user = self.request.user
active_user_following = active_user.following.values_list('user_id', flat=True)
following_user_objects = []
context['following'] = following_user_objects
context['followed_user_pots'] = Post.objects.filter(user__in=following_user_objects)
for id in active_user_following:
followed = User.objects.get(id=id)
following_user_objects.append(followed)
return context
This is my HTML code:
{% for user in following %}
{{user}}
{% for post in user.post %}
{{post}}
{% endfor %}
{% endfor%}
All the above HTML displays is the username of the users in following. Is there some other way I need to access the posts?
This is the Post model:
class Post(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE, null=True)
topic = models.ForeignKey(Topic, on_delete=models.CASCADE, null=True)
post = models.CharField(max_length=200)
date_added = models.DateTimeField(default=timezone.now)
First I think in values_list you have to put id not user_id, because you want to get ids of the following users. and also that's much better practice when you get query logic in get_queryset method. so you don't need to add followed_user_pots in context it's better to remove it and instead use this code for getting what you want.
def get_queryset(self):
qs = super().get_queryset()
active_user = self.request.user
active_user_following = active_user.following.values_list('id', flat=True)
return Post.objects.filter(user__id__in=following_user_objects)
in template you can access posts by iterating through object_list
{% for post in object_list %}
{{post}}
{% endfor %}
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.
I need to pass id from one template to another template. In template i am iterating over one model
{% for project in all_projects %}
<h3>{{ project.name }}</h3>
{% endfor %}
This going to one template where my url looks like
url(r'^$', views.ProjectsListView.as_view(), name='index'),
url(r'^platforms/$', views.PlatformsIndexView.as_view(), name='platforms'),
url(r'^platforms/nodes/$', views.PlatformsNodesListView.as_view(), name='platforms_list'),
Browser url that i have is http://127.0.0.1:8000/platforms/?project=1
that's ok good. But from second template i need to send third template another parametrs and filters. So how do i can get id of project?
I can not send now project id to third template because i am not iterating over it. How to remember id of project?
views.py
class ProjectsListView(ListView):
template_name = 'project/projects.html'
model = Project
context_object_name = 'all_projects'
class PlatformsIndexView(TemplateView):
template_name = 'project/platforms.html'
class PlatformsNodesListView(ListView):
template_name = 'project/general.html'
model = Platform
context_object_name = 'all_platforms'
def get_queryset(self):
queryset = super().get_queryset()
type_filter = self.request.GET.get('type')
project_filter = self.request.GET.get('project')
if type_filter in [Platform.BACKEND, Platform.ANDROID, Platform.IOS, Platform.FRONTEND]:
queryset = queryset.filter(type=type_filter)
if project_filter:
queryset = queryset.filter(project__id__exact=project_filter)
else:
raise Http404
return queryset
Please explain me.
Thank you in advance
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'])