【问题标题】:How do I properly use javascript axios .get() function to call get_queryset() function in Django viewset?如何正确使用 javascript axios .get() 函数在 Django 视图集中调用 get_queryset() 函数?
【发布时间】:2020-11-13 23:08:25
【问题描述】:

我按照 youtube 指南实现了一个 React/Redux 前端,该前端使用 javascript axios 向 Django REST 框架后端发出请求。我一直在为它添加很多我自己的作品。如果您认为需要它来回答我的问题,这是原始的 github 存储库,尽管您不应该: Link To Github

我有一种新方法可以用来获取我所说的eventdefinitions。有时我想要数据库中的所有eventdefinitions,但有时我只想要其中的一些。在原始指南中,我被教导获取数据的唯一方法是获取所有数据,因此要获取所有 eventdefinitions,我将执行以下操作:

在javascript中,我使用以下实现axios的方法:

// GET EVENT DEFINITIONS
export const getEventDefinitions = () => (dispatch, getState) => {
  axios
    .get("/api/eventdefinitions/", tokenConfig(getState))
    .then((res) => {
      dispatch({
        type: GET_EVENTDEFINITIONS,
        payload: res.data,
      });
    })
    .catch((err) =>
      dispatch(returnErrors(err.response.data, err.response.status))
    );
};

在我的urls.py 文件中,我为/api/eventdefinitions/ url 设置了url_patterns:

from rest_framework import routers
from .api import ... EventDefinitionViewSet, ...

router = routers.DefaultRouter()

...
router.register('api/eventdefinitions', EventDefinitionViewSet, 'eventdefinitions')
...

urlpatterns = router.urls

此文件中的EventDefinitionViewSet来自api.py文件:

from .models import ... EventDefinition, ... //not really sure why this is imported, irrelevant
from rest_framework import viewsets, permissions
from .serializers import ... EventDefinitionSerializer, ...

...

class EventDefinitionViewSet(viewsets.ModelViewSet):
    permission_classes = [
        permissions.IsAuthenticated
    ]

    serializer_class = EventDefinitionSerializer

    def get_queryset(self):
        return self.request.user.eventdefinitions.all()

    def perform_create(self, serializer):
        serializer.save(owner=self.request.user)

...

EventDefinitionSerializer 在我的serializers.py 文件中实现:

from rest_framework import serializers
from .models import ... EventDefinition, ...

class EventDefinitionSerializer(serializers.ModelSerializer):
    class Meta:
        model = EventDefinition
        fields = '__all__'

最后一段代码是文件models.py,它实现了EventDefinition模型:

class EventDefinition(models.Model):
    event_id = models.SmallIntegerField(primary_key=True)
    event_name = models.CharField(max_length=50)
    priority = models.SmallIntegerField()
    recurring = models.BooleanField()
    active_for_generation = models.BooleanField()
    owner = models.ForeignKey(
        User, related_name="eventdefinitions", on_delete=models.CASCADE, null=True)

我使用 React/Redux,我将所有 eventdefinitions 和函数 getEventDefinitions 放入 props,最后,我在我的 React 函数 componentDidMount() 中调用函数 getEventDefinitions

componentDidMount() {
    this.props.getEventDefinitions();
}

我提到这一切是为了说明这完全符合预期。当我调用this.props.getEventDefinitions() 时,我可以将所有eventdefinitions 放入组件的道具中。我不确定的部分来了。如何仅选择其中一些eventdefinitions。我希望能够获得所有这些,添加最后一个(最大的event_id),添加第一个(最小的event_id),并通过其event_id 获得eventdefinition。我发现了很多关于多个 stackoverflow 线程的有用信息,并且我已经实现了所有这些方法。奇怪的是,这些都不起作用,甚至没有得到所有的eventdefinitions,尽管没有太大的改变来得到这个。我改变了一些东西来尝试做到这一点。我会按照之前的顺序去。

我更改了axios 位,方法是使用一个可以采用多个值的参数。我称之为event_id,但实际上它可以有许多不同的值。此代码通知我存在问题,但不会引发任何错误。我知道有一个问题,因为我的 Redux 商店没有显示 GET_EVENTDEFINITIONS 操作已被调用。这意味着永远不会触发.then,这意味着永远不会有响应。请注意,我更改了网址,使其具有额外的?event_id=${event_id}。我了解到如果我这样写url,event_id的值可以在ViewSet中拉出来:

// GET EVENT DEFINITIONS
export const getEventDefinitions = (event_id) => (dispatch, getState) => {
  axios
    .get(`/api/eventdefinitions?event_id=${event_id}`, tokenConfig(getState))
    .then((res) => {
      dispatch({
        type: GET_EVENTDEFINITIONS,
        payload: res.data,
      });
    })
    .catch((err) =>
      dispatch(returnErrors(err.response.data, err.response.status))
    );
};

在我的urls.py 中没有任何变化:

...

这个文件中的EventDefinitionViewSet 来自api.py 文件变化很大,这是我试图提取我在 axios javascript 位中输入的event_id 值的地方(上面的两个代码块) .如果我不得不猜测我做错了什么,它就在这个文件中。我的理由是,由于我没有得到响应,可能是因为当我调用 .get 时,要么根本没有调用此文件中的 get_queryset 函数,因此没有响应,要么正在调用 get_queryset ,但event_id 没有'all''last''first' 的值:

from .models import ... EventDefinition, ... //not really sure why this is imported, irrelevant
from rest_framework import viewsets, permissions
from .serializers import ... EventDefinitionSerializer, ...

...

class EventDefinitionViewSet(viewsets.ModelViewSet):
    permission_classes = [
        permissions.IsAuthenticated
    ]

    serializer_class = EventDefinitionSerializer

    def get_queryset(self):

        event_id = self.request.GET.get("event_id")

        if event_id == 'all':
            return self.request.user.eventdefinitions.all()
        elif event_id == 'last':
            return [self.request.user.eventdefinitions.order_by("-event_id")[0]]
        elif event_id == 'first':
            return [self.request.user.eventdefinitions.order_by("event_id")[0]]
        else:
            return [self.request.user.eventdefinitions.get(pk=event_id)]

    def perform_create(self, serializer):
        return serializer.save(owner=self.request.user)

...

EventDefinitionSerializer 不变:

...

models.py 文件没有改变:

...

最后,我在我的 React componentDidMount 生命周期函数中调用了 getEventDefinitions 函数。这也可能是一个问题,但我不这么认为,因为我已经尝试了很多东西,起初我遇到了很多 https 错误,但是当我尝试这个时,它们就消失了(当然仍然可能有问题,但这是我能做的最好的):

componentDidMount() {
    this.props.getEventDefinitions.bind(this, 'all');
}

我应该提一下,当调用 getEventDefinitions() 时,它会调用一个 reducer 函数,该函数几乎只是将值添加到状态中,但是由于我知道 .then 函数没有被调用,所以没有理由知道这是如何处理的。最后,我如何更改文件以补偿增加的输入值的问题是什么?它是我的视图集吗?或者可能是其他问题?

【问题讨论】:

    标签: reactjs django redux django-rest-framework axios


    【解决方案1】:

    你要找的是DRF filtering

    也许您应该将过滤器重命名为 event_filter

    例子:

        def get_queryset(self):
    
            queryset = EventDefinition.objects.all()
    
            event_filter = self.request.query_params.get('event_filter', None)
    
            if event_filter == 'last':
                return [queryset.order_by("-event_id")[0]]
            if event_filter == 'first':
                return [queryset.order_by("event_id")[0]]
    
            return queryset
    

    网址:

    • 获取所有/api/eventdefinitions
    • 通过 event_id(主键)/api/eventdefinitions/1 选择 1 是您的主键
    • 最后:/api/eventdefinitions/?event_filter=last
    • 获得第一名:/api/eventdefinitions/?event_filter=first

    顺便说一句,我现在正在处理tutorials on how to build SaaS application from scratch with Django and React 系列。你可能会觉得很有趣。

    【讨论】:

      【解决方案2】:

      我最终为 get_queryset 函数做了这样的事情:

      def get_queryset(self):
      
          queryset = EventDefinition.objects.all()
      
          event_filter = self.request.GET.get("event_filter", None)
      
          if event_filter == 'last':
              ordered_queryset = queryset.order_by("-event_id")
              if ordered_queryset.count() == 0:
                  return []
              else:
                  return [ordered_queryset.first()]
      
          if event_filter == 'first':
              ordered_queryset = queryset.order_by("event_id")
              if ordered_queryset.count() == 0:
                  return []
              else:
                  return [ordered_queryset.first()]
      
          return queryset
      

      我为 axios 部分做了这个:

      // GET EVENT DEFINITIONS
      export const getEventDefinitions = (event_id) => (dispatch, getState) => {
      
        const getString = typeof(event_id) === "number" ?
          `/api/eventdefinitions/${event_id}/` :
          (typeof(event_id) === "string" ?
            `/api/eventdefinitions?event_filter=${event_id}` :
            "/api/eventdefinitions/")
      
        axios
          .get(getString, tokenConfig(getState))
          .then((res) => {
            dispatch({
              type: GET_EVENTDEFINITIONS,
              payload: res.data,
            });
          })
          .catch((err) =>
            dispatch(returnErrors(err.response.data, err.response.status))
          );
      };
      

      【讨论】:

      • 感谢 pplonski 的回答帮助我解决了这个问题。
      猜你喜欢
      • 2019-06-21
      • 2020-09-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-01-21
      • 2021-02-21
      相关资源
      最近更新 更多