简体   繁体   English

如何在DRF viewsets.ModelViewSet中查询相关object

[英]How to query related object in DRF viewsets.ModelViewSet

I have a serialised model (Job) which I am using with datatables.我有一个与数据表一起使用的序列化 model (Job)。 The "Job" model is related to another model (Board) and here is where my problem is. “工作” model 与另一个 model(板)相关,这就是我的问题所在。 I followed the doc here to filter jobs that are related to the "Board" model which is currently being viewed, but I can't get it to work as intended.我按照此处的文档过滤了与当前正在查看的“板”model 相关的作业,但我无法让它按预期工作。

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')

You have to give the __ for ForeignKey lookups.您必须为ForeignKey查找提供__ So, get_queryset method be like:因此, 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

For anyone with a similar issue, kindly take a look at alanjds/drf-nested-routers .对于有类似问题的任何人,请查看alanjds/drf-nested-routers This is what I used and it worked perfectly.这就是我使用的,并且效果很好。

Here is an overview of what I did.这是我所做的概述。

After installing the package with pip install drf-nested-routers .安装 package 和pip install drf-nested-routers

According to the docs,根据文档,

It is not needed to add this library in your Django project's settings.py file, as it does not contain any app, signal or model.不需要在 Django 项目的 settings.py 文件中添加此库,因为它不包含任何应用程序、信号或 model。

In my app urls.py file, I created parent and child routers在我的应用程序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)),
]

Then in my serializers.py , I created a HyperlinkedModelSerializer然后在我的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...

I went on to my views.py to create my viewsets and added the get_queryset params我继续我的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'])

Once you do these, you should be able to access your APIs via完成这些操作后,您应该能够通过以下方式访问您的 API

/parent_url/{{parent_pk}}/child_list/{{child_pk}}

Now, because of my peculiar need (I wanted to use this on datatables to filter related objects), I added the URLs of my APIs to the head of my base.html so that the URLs can be loaded dynamically since I can't load such in my javascript file现在,由于我的特殊需要(我想在数据表上使用它来过滤相关对象),我将我的 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>
...

And in my main.py file, I did the following在我的main.py文件中,我做了以下

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM