【问题标题】:How to filter against URL with foreign key field in Django REST, overwriting get_queryset method correctly如何在 Django REST 中使用外键字段过滤 URL,正确覆盖 get_queryset 方法
【发布时间】:2019-12-25 11:42:37
【问题描述】:

我正在尝试使用 django REST 根据 url 过滤我的查询集,但无法真正让它工作。

我想在 URL 中传递一个字符串(项目名称)。根据这个作为外键的字符串,我想过滤我的查询集(BuildingGroup)。

我不想使用查询参数,而是使用 url 过滤器。我关注了文档,但网站上没有太多内容。

这就是我正在尝试的:

class ListBuildingGroupProject(ListAPIView):
    serializer_class    = BuildingGroupSerializer
    filter_fields       = 'project'

    def get_queryset(self):

        project = self.kwargs['project']
        building_groups = BuildingGroup.objects.filter(project=project)
        result = building_groups.order_by('-creation_date')

        return result

在线building_groups = BuildingGroup.objects.filter(project=project) throws me a KeyError for project.

Here are my models. Note that BuildingGroup has one Project. A project can belong to many BuildingGroups. 

class BuildingGroup(models.Model):
    description           = models.CharField(max_length=500, null=True, blank=True)
    project               = models.ForeignKey(Project, on_delete=models.CASCADE)
    creation_date         = models.DateTimeField(auto_now=False)
   class Project(models.Model):
       project_name            = models.CharField(max_length=120, primary_key=True, unique=True)
       start_date              = models.DateTimeField(auto_now=False, null=True, blank=True)
       end_date                = models.DateTimeField(auto_now=False, null=True, blank=True)


这里是我的网址:

    path('project/<str:project_name>', ListBuildingGroupProject.as_view(), name='building-group-project'),

非常感谢您的帮助!提前致谢!

【问题讨论】:

  • building_groups = BuildingGroup.objects.filter(project__project_name=project)?
  • @RaideR 感谢您的提示,它仍然给了我关键错误。我认为self.kwargs['project'] 没有访问我在 URL 中传递的参数.... 或者我通常不正确地使用过滤器?

标签: python django django-rest-framework django-filter


【解决方案1】:

在您的网址中,您的参数称为project_name。这是你应该从 kwargs 那里得到的。此外,您希望它与 project.project_name 匹配:

def get_queryset(self):

    project_name = self.kwargs['project_name']
    building_groups = BuildingGroup.objects.filter(project__project_name=project_name)
    result = building_groups.order_by('-creation_date')

    return result

【讨论】:

  • 非常感谢我的朋友,工作就像一个魅力!所以一般来说我必须使用模型的名称然后是字段?喜欢 model__fieldname?
  • 这是因为你跨越了一个关系。有关该主题的更多详细信息,请参阅docs.djangoproject.com/en/2.2/topics/db/queries/…
  • 知道了!非常感谢!
【解决方案2】:

你可能想看看这个DRF documentation 关于这个。 需要安装Django Filters

你只需要在一些rest_filters.py

中声明
from django_filters import rest_framework as filters
from .models import BuildingGroup
class BuildingGroupFilter(filters.FilterSet):
   class Meta:
       model = BuildingGroup
       fields = { 
           "project__name":["exact","icontains"],
           "project":["exact","in"]
       }

然后在您的 ViewSet 声明中: [...] 从 .rest_filters 导入 BuildingGroupFilter

class ListBuildingGroupProject(ListAPIView):
    serializer_class=BuildingGroupSerializer
    filterset_class = BuildingGroupFilter

您现在可以通过以下方式享受宁静的行为: {path_to_your_endpoint}?project__name__icontains="Hello World"{path_to_your_endpoint}?project__=[Project Id List]

为了检查事情的运作方式,可浏览的 API 中提供了过滤器。

【讨论】:

  • 感谢朱利安的回答。听起来是个不错的选择。我决定坚持使用查询集的简单覆盖,因为它看起来更简单并且没有额外的依赖项。但我将来可能会实施。非常感谢!
猜你喜欢
  • 2020-05-03
  • 2021-07-16
  • 2020-11-08
  • 1970-01-01
  • 2012-06-27
  • 2020-10-07
  • 1970-01-01
  • 1970-01-01
  • 2014-08-24
相关资源
最近更新 更多