【发布时间】: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