【问题标题】:DJANGO REST API ---Javascript function not generating right PKDJANGO REST API ---Javascript 函数没有生成正确的 PK
【发布时间】:2017-07-08 02:21:14
【问题描述】:

使用 Django REST API,根据偏好(年龄、性别、大小)向用户显示狗。用户可以喜欢或不喜欢狗。然后根据他们设定的偏好向他们展示下一只狗(假设他们还没有看到它)。

应用程序向用户显示第一只狗(基于首选项-UserPref 模型),但是当他们点击喜欢或不喜欢时,它不会移动到下一只狗并生成如下所示的未找到错误:

未找到:/api/dog/undefined/disliked/next

未定义的应该是下一条狗的 PK

因此,要么我的 python 逻辑没有生成正确的 PK(如错误代码中的“未定义”所示),要么由于某种原因,javascript 代码没有为 PK 获取正确的格式化数字。只是不确定可能是什么问题。

这是我的模型:

class Dog(models.Model):
    name = models.CharField(max_length=255)
    image_filename = models.CharField(max_length=255, default='')
    breed = models.CharField(max_length=255, default='Unknown Breed')
    age = models.IntegerField()
    gender = models.CharField(choices=GENDER, max_length=1)
    size = models.CharField(choices=SIZE, max_length=2)

    @property
    def get_image_url(self):
        return self.image_filename.name

    def __str__(self):
        return self.name


class UserDog(models.Model):
    user = models.ForeignKey(User, on_delete=models.CASCADE, null=True)
    dog = models.ForeignKey(Dog, on_delete=models.CASCADE)
    status = models.CharField(choices=STATUS, max_length=2)

    class Meta:
        unique_together = ('user', 'dog')

    def __str__(self):
        return '{} {} {}'.format(self.user, self.dog, self.get_status_display())


class UserPref(models.Model):
    user = models.ForeignKey(User, on_delete=models.CASCADE)
    age = models.CharField(max_length=7, default='b,y,a,s')
    gender = models.CharField(max_length=3, default='m,f')
    size = models.CharField(max_length=8, default='s,m,l,xl')

    def __str__(self):
        return '{} preferences'.format(self.user)

和View对应的Dog Selection for Next

AGES = {
    'b': list(range(0, 6)),
    'y': list(range(6, 18)),
    'a': list(range(18, 72)),
    's': list(range(72, 192))
}


def get_ages(keys='b,y,a,s'):
    """Returns age ranges in years."""
    data = []
    for key in keys.split(','):
        data.extend(AGES[key])
    return data



class DogFilterView(generics.RetrieveAPIView):
    permission_classes = (permissions.IsAuthenticated,)
    serializer_class = serializers.DogSerializer

    def get_ids(self, queryset=None):
        if queryset is not None:
            return [userdog.dog.pk for userdog in queryset]
        return []

    def filter_pref(self, dog_filter, user_prefs):
        userdog_query = models.UserDog.objects.filter(user=user_prefs.user.pk
                                                      ).select_related('dog')
        ages = get_ages(user_prefs.age)
        queryset = models.Dog.objects.filter(
            gender__in = user_prefs.gender.split(','),
            size__in = user_prefs.size.split(','),
            age__in = ages
        )
        if dog_filter not in STATUSES:
            dogs = self.get_ids(userdog_query)
            queryset = queryset.exclude(pk__in=dogs)
        else:
            userdog_query = userdog_query.filter(status=dog_filter[0])
            dogs = self.get_ids(userdog_query)
            queryset = queryset.filter(pk__in=dogs)

        return queryset.order_by('pk')

    def get_queryset(self):
        user = self.request.user
        dog_filter = self.kwargs.get('dog_filter')
        # Get user preferences
        user_prefs = get_object_or_404(models.UserPref, user=user)
        # Get age ranges(months) based on user preference selections
        queryset = self.filter_pref(dog_filter, user_prefs)
        return queryset

    def get_object(self):
        pk = int(self.kwargs.get('pk'))
        # Filter the query for the NEXT dog by pk.
        queryset = self.get_queryset().filter(
            pk__gt=pk
        )
        obj = queryset.first()
        if not obj:
            raise Http404
        return obj

然后是我的正则表达式:

url(r'^api/dog/(?P<pk>-?\d+)/(?P<dog_filter>liked|disliked|undecided)/next/$',
        DogFilterView.as_view(),
        name='dog-filter-detail'),

我的狗类序列化器:

class DogSerializer(serializers.ModelSerializer):
    class Meta:
        fields = (
            'name',
            'image_filename',
            'breed',
            'age',
            'gender',
            'size'
        )
        model = models.Dog

另外请注意,我没有在此处编写的 Javascript 的一部分我认为可能需要检查但不确定 --- 这是获取下一条狗的函数:

getNext: function () {
    this.serverRequest = $.ajax({
      url: `api/dog/${ this.state.details ? this.state.details.id : -1 }/${ this.state.filter }/next/`,
      method: "GET",
      dataType: "json",
      headers: TokenAuth.getAuthHeader()
    }).done(function (data) {
      this.setState({ details: data, message: undefined });
    }.bind(this)).fail(function (response) {
      var message = null;
      if (response.status == 404) {
        if (this.state.filter == "undecided") {
          message = "No dogs matched your preferences.";
        } else {
          message = `You don't have any ${ this.state.filter } dogs.`;
        }
      } else {
        message = response.error;
      }
      this.setState({ message: message, details: undefined });
    }.bind(this));

【问题讨论】:

  • undefined 是一个 JavaScript 原语。是什么让您认为 python api 有问题?如果this.state.details 为假/缺失或this.state.details.id 缺失,则问题末尾的javascript 表达式将导致此类错误。
  • 因为它应该为 生成一个值。数据库中有 30 只奇怪的狗,即使选择了所有偏好,它也不会前进到下一只狗。
  • 实现“next”的代码在哪里? Python 没有undefined,所以错误一定在你的 javascript 中。
  • 无论如何,我们不可能知道您的 api 应该如何工作,因为您没有包含序列化程序类。 minimal reproducible example
  • 好的,明白了。代码可能会变得不堪重负,所以在这里复制我的 git 存储库:github.com/pythoncreate/pugorugh

标签: javascript python django angular rest


【解决方案1】:

因此,经过数小时无休止的研究,我想通了。我没有将“id”字段传递给 DogSerializer,因此 pk 没有被传递。哇,感谢上帝。

【讨论】:

    猜你喜欢
    • 2018-12-09
    • 1970-01-01
    • 2015-07-14
    • 2016-01-09
    • 2016-05-30
    • 2021-01-14
    • 2017-04-19
    • 1970-01-01
    • 2019-03-21
    相关资源
    最近更新 更多