如何在同一个基于类的视图EX:User Profile和Friends下拥有两个单独的查询集

时间:2017-09-08 16:31:31

标签: python django django-models pki

在我之前提出的一个问题:如何在同一个基于类的视图下拥有两个单独的查询集。由于语法错误,最初的问题很简单但在修复之后我得到:get() got an unexpected keyword argument 'pk'我认为这是我写我的观点的一个问题。

编辑:澄清问题:如何使用两个查询集,一个调用用户的pk信息,另一个调用用户列出同一类的用户列表。

views.py

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)

urls.py

# 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>

2 个答案:

答案 0 :(得分:2)

如您所见,您的view_profile_with_pk网址格式需要pk参数:

url(r'^profile/(?P<pk>\d+)/$', views.ViewProfile.as_view(), name='view_profile_with_pk')

但是在ViewProfile视图中,您已将get()方法配置为:

def get(self, request):
    # ...

您可以清楚地注意到get()采用完全两个参数,即selfrequest。任何地方都没有pk。所以Django不知道它。

然而

您可以在*args函数中添加**kwargsget()个参数,这些参数将处理您的网址参数:

def get(self, request, *args, **kwargs):
    # ...

然后你可以在函数中自由地获得pk

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)

但是我不明白为什么你定义了view_profile函数,而你可以在get()函数中实现它的逻辑:

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)

这将有效,直到您向视图提供不存在的pk。这将导致异常。您可以使用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)

现在你应该有一个功能齐全的视图。

修改

正如您刚才所说,该视图返回相同的User数据。这是因为:

users = User.objects.all()

这一行毫无意义,因为每次用户向您的视图发送请求时,他都会在users中获得context属性,该属性只包含您数据库中的所有用户。

一种可能且更有意义的解决方案是将当前用户附加到此属性:

# ...
context = {'object_list': object_list, 'user': owner}
# _______________________________________^

return render(request, self.template_name, context)

现在该视图将返回Post及其相关的User

答案 1 :(得分:1)

你可以尝试这样吗

def view_profile(request, *args, **kwargs, pk=None):
        if 'pk' in kwargs:
            user = User.objects.get(pk=kwargs['pk'])
        else:
            user = request.user
        kwargs = {'user': request.user}
        return render(request, 'accounts/profile.html', kwargs)