【问题标题】:How to query related object in DRF viewsets.ModelViewSet如何在 DRF viewsets.ModelViewSet 中查询相关对象
【发布时间】:2021-06-13 19:37:22
【问题描述】:

我有一个与数据表一起使用的序列化模型(作业)。 “工作”模型与另一个模型(板)相关,这就是我的问题所在。我按照文档here 过滤了与当前正在查看的“Board”模型相关的作业,但我无法使其按预期工作。

models.py

class Board(models.Model):
    name = models.CharField(_('board name'), max_length=256)
    slug = models.SlugField(_('unique url'), null=True, blank=True)
...


class Job(models.Model):
    board = models.ForeignKey(Board, on_delete=models.CASCADE, verbose_name=_('board'))
...

views.py

 class JobDataTablesViewSet(viewsets.ModelViewSet):
        queryset = Job.objects.all().order_by('-date_posted')
        serializer_class = JobDatatablesSerializer
        filter_backends = (DatatablesFilterBackend,)
        filterset_class = JobGlobalFilter
    
        def get_queryset(self):
            slug = self.kwargs['slug']
            queryset = Job.objects.filter(board__slug=slug)
            return queryset

urls.py

path('<slug:slug>/', views.BoardPublicView.as_view(), name='public-board')

【问题讨论】:

标签: django django-rest-framework datatables django-datatable


【解决方案1】:

您必须为ForeignKey 查找提供__。所以,get_queryset 方法是这样的:

slug = models.SlugField(
    unique=True,
    default=self.slug, # This is not from the tutorial, it's a modification
    # to demonstrate here.
    max_length=13,
)

def get_queryset(self):
    slug = self.kwargs['slug']
    queryset = Job.objects.filter(board__slug=slug)
    return queryset

【讨论】:

  • 是的,我这样做了,但它引发了 keyError["slug"]
【解决方案2】:

对于有类似问题的任何人,请查看alanjds/drf-nested-routers。这是我用过的,效果很好。

以下是我所做工作的概述。

使用pip install drf-nested-routers安装包后。

根据文档,

不需要在你的 Django 项目的 settings.py 文件中添加这个库,因为它不包含任何应用程序、信号或模型。

在我的应用程序urls.py 文件中,我创建了父路由器和子路由器

router = routers.SimpleRouter()
router.register(r'boards', views.BoardViewSet, basename="boards_api_list")

boards_router = routers.NestedSimpleRouter(router, r'boards', lookup='board')
boards_router.register(r'jobs', views.JobViewSet, basename='board_jobs_list')

urlpatterns = [
    path('api/', include(router.urls)),
    path('api/', include(boards_router.urls)),
]

然后在我的serializers.py 中,我创建了一个HyperlinkedModelSerializer

class BoardSerializer(serializers.HyperlinkedModelSerializer):
    owner = UserSerializer()
    jobs = NestedHyperlinkedRelatedField(
        many=True,
        read_only=True,
        view_name='jobs_view_name',
        parent_lookup_kwargs={'slug': 'board__slug'}
    )

    class Meta:
        model = Board
        fields = [...]
        extra_kwargs = {
            'url': {'view_name': 'my_custom_view_name', 'lookup_field': 'slug'},
            ...other desired kwargs...
        }

class JobViewSet(serializers.ModelSerializer):
    ...standard serializer settings...

我继续使用我的 views.py创建我的视图集并添加了 get_queryset 参数

class JobViewSet(viewsets.ModelViewSet):
    queryset = Job.objects.all().order_by('-date_posted')
    serializer_class = JobSerializer
    filter_backends = (DatatablesFilterBackend,)
    filterset_class = JobGlobalFilter

    def get_queryset(self):
        return Job.objects.filter(board__slug=self.kwargs['board_slug'])

完成这些操作后,您应该能够通过

访问您的 API
/parent_url/{{parent_pk}}/child_list/{{child_pk}}

现在,由于我的特殊需求(我想在数据表上使用它来过滤相关对象),我将我的 API 的 URL 添加到我的 base.html 的头部,以便可以动态加载 URL,因为我可以'不要在我的 javascript 文件中加载这样的文件

...
<head>
    <script>var boardListUrl= "{% url 'boards:boards_api_list-list' %}?format=datatables"</script>
    {% if board.slug %}
    <script>var jobListUrl= "{% url 'boards:board_jobs_list-list' board.slug %}?format=datatables"</script>
    {% endif %}
<head>
...

在我的main.py 文件中,我做了以下操作

 var table = $('#tableName').DataTable({
        ...
        "ajax": jobListUrl,
        ...
});

【讨论】:

    猜你喜欢
    • 2019-06-18
    • 2019-08-27
    • 1970-01-01
    • 2020-07-16
    • 1970-01-01
    • 2021-07-24
    • 1970-01-01
    • 2019-12-13
    • 1970-01-01
    相关资源
    最近更新 更多