On an earlier question I asked: How to have two separate querysets under the same class based view. The initial problem was a simple due to a syntax error but after fixing it i got :get() got an unexpected keyword argument 'pk'
I believe it to be a problem on how i wrote my views.
EDIT: Clarifying the issue: is how to have two querysets one calling User's pk info and one making a list of users under the same class.
class ViewProfile(generic.ListView):
model = Post
template_name = 'accounts/profile.html'
def view_profile(request, pk=None):
if pk:
user = User.objects.get(pk=pk)
else:
user = request.user
kwargs = {'user': request.user}
return render(request, 'accounts/profile.html', kwargs)
def get(self, request):
users =User.objects.all()
object_list= Post.objects.filter(owner =self.request.user).order_by('-timestamp')
args ={'object_list':object_list,'users':users}
return render (request, self.template_name, args)
# profilepage
url(r'^profile/$', views.ViewProfile.as_view(), name='view_profile'),
# profilepage
url(r'^profile/(?P<pk>\d+)/$', views.ViewProfile.as_view(), name='view_profile_with_pk'),
<div class="col-md-4">
<h1>Friends</h1>
{%for user in users %}
<a href="{% url 'accounts:view_profile_with_pk' pk=user.pk %}">
<h3>{{user.username}}</h3>
</a>
{%endfor%}
</div>
As you see, your view_profile_with_pk
url pattern takes a pk
paramter:
url(r'^profile/(?P<pk>\d+)/$', views.ViewProfile.as_view(), name='view_profile_with_pk')
But then in your ViewProfile
view you have configured your get()
method like:
def get(self, request):
# ...
You can clearly notice that get()
takes exactly two parameters, which are self
and request
. There is no pk
anywhere. So Django doesn't know about it.
Yet.
You can add *args
and **kwargs
arguments to the get()
function, which will take care of your url parameters:
def get(self, request, *args, **kwargs):
# ...
And then you can freely get your pk
inside the function:
def get(self, request, *args, **kwargs):
pk = kwargs.get('pk') # <<<
users = User.objects.all()
object_list = Post.objects.filter(owner=request.user).order_by('-timestamp')
context = {'object_list': object_list, 'users': users}
return render(request, self.template_name, context)
But I don't understand why you have defined the view_profile
function, while you can implement it's logic inside the get()
function:
def get(self, request, *args, **kwargs):
pk = kwargs.get('pk')
owner = User.objects.get(pk=pk) if pk else request.user # <<<
users = User.objects.all()
object_list = Post.objects.filter(owner=owner).order_by('-timestamp')
# ________________________________^
context = {'object_list': object_list, 'users': users}
return render(request, self.template_name, context)
This will work, until you provide a non-existing pk
to the view. This will result an exception. You can fix that by using get_object_or_404()
:
from django.shortcuts import get_object_or_404
def get(self, request, *args, **kwargs):
pk = kwargs.get('pk')
owner = get_object_or_404(User, pk=pk) if pk else request.user # <<<
users = User.objects.all()
object_list = Post.objects.filter(owner=owner).order_by('-timestamp')
context = {'object_list': object_list, 'users': users}
return render(request, self.template_name, context)
Now you should have a fully functional view.
EDIT:
As you've just stated, the view returns the same User
data. This is because of:
users = User.objects.all()
This line is meaningless, because every time the user sends a request to your view, he will get a users
property in the context
, which just holds all the users in your database.
A possible and more meaningful solution will be to attach the current user to this property:
# ...
context = {'object_list': object_list, 'user': owner}
# _______________________________________^
return render(request, self.template_name, context)
Now the view will return the Post
s and their related User
.