【发布时间】:2019-10-15 17:11:13
【问题描述】:
rest_framework.viewsets.ReadOnlyModelViewSet 有问题。
class ProductFilter(filters.FilterSet):
meat_type = filters.CharFilter(lookup_expr='slug__iexact')
category = filters.CharFilter(lookup_expr='slug__iexact')
class Meta:
model = Product
fields = {
'price': ['gte', 'lte'],
}
ordering_fields = ['price', ]
class ProductViewSet(viewsets.ReadOnlyModelViewSet):
queryset = Product.objects.all()
serializer_class = ProductSerializer
filterset_class = ProductFilter
@action(methods=['get'], detail=False)
def get_products(self, request):
products = self.get_queryset().order_by('-created')
serializer = self.get_serializer_class()(products, many=True)
print('SHOW IT')
if len(products) == 0:
return Response(status=status.HTTP_204_NO_CONTENT)
return Response(serializer.data, status=status.HTTP_200_OK)
我的问题是 get_products 中的 print 不起作用,但代码使用过滤器对象给出了很好的结果。我的网址:
router = routers.DefaultRouter()
router.register('', views.ProductViewSet)
urlpatterns = [
path('shop/', include(router.urls))
]
测试:
class TestViews(TestCase):
def setUp(self):
self.client = Client()
self.url = "/api/shop/"
self.search_url = "/api/shop/?price__lte={}&price__gte={}&meat_type={}&category={}"
self.category1 = Category.objects.create(name='cattest1',
slug='cattest1')
self.category2 = Category.objects.create(name='cattest2',
slug='cattest2')
self.meat_type1 = MeatType.objects.create(name='meattest1',
slug='meattest1')
self.meat_type2 = MeatType.objects.create(name='meattest2',
slug='meattest2')
self.product1 = Product.objects.create(category=self.category1,
meat_type=self.meat_type2,
name='prodtest1',
slug='prodtest1',
price=50)
self.product2 = Product.objects.create(category=self.category1,
meat_type=self.meat_type1,
name='prodtest2',
slug='prodtest2',
price=75)
self.product3 = Product.objects.create(category=self.category2,
meat_type=self.meat_type2,
name='prodtest3',
slug='prodtest3',
price=20)
self.product4 = Product.objects.create(category=self.category2,
meat_type=self.meat_type1,
name='prodtest4',
slug='prodtest4',
price=150)
def test_get_products_all(self):
response = self.client.get(self.url)
self.assertEqual(200, response.status_code)
self.assertEqual(4, len(response.data))
def test_get_products_no_content(self):
Product.objects.all().delete()
response = self.client.get(self.url)
self.assertEqual(204, response.status_code)
def test_product_greater_than(self):
response = self.client.get(self.search_url.format(
"", "55", "", ""
))
self.assertEqual(200, response.status_code)
self.assertEqual(2, len(response.data))
测试test_get_products_no_content 失败并出现错误:
assertionError: 204 != 200。
有人知道吗?
感谢您的任何回答
马格努斯
编辑
创建此函数,是将好的数据传递给过滤器。
DICT {'price__lte': '50', 'price__gte': '100', 'meat_type': 'wieprzowina'}
但是当我把它作为过滤参数时我有问题。出现错误:
int() 以 10 为底的无效文字:'wieprzowina'。它尝试将字符串更改为数字,但我不知道为什么。
def get_queryset(self):
filter_params = self.request.query_params
filter_params_dict = {k: str(v) for (k, v) in filter_params.dict().items()
if v is not None and str(v) != ""}
print('DICT', filter_params_dict)
queryset = Product.objects.filter(**filter_params_dict)
return queryset
编辑2:
class Product(models.Model):
category = models.ForeignKey(Category,
related_name='products',
on_delete=models.CASCADE)
meat_type = models.ForeignKey(MeatType,
on_delete=models.CASCADE)
name = models.CharField(max_length=150,
db_index=True)
slug = models.SlugField(max_length=150,
db_index=True)
image = models.ImageField(upload_to='products/%Y/%m/%d',
default='no-image.png')
description = models.TextField(blank=True)
price = models.DecimalField(max_digits=10, decimal_places=2)
available = models.BooleanField(default=True)
created = models.DateTimeField(auto_now_add=True)
updated = models.DateTimeField(auto_now=True)
class Meta:
ordering = ('price',)
index_together = (('id', 'slug'),)
def __str__(self):
return self.name
def get_absolute_url(self):
return reverse('shop:detail',
args=[self.category.slug, self.id, self.slug])
【问题讨论】:
-
您使用的是哪个
TestCase?来自django?这可能是因为之前的测试已经删除了所有产品,所以test_product_greater_than找不到任何产品,然后返回 204 代码而不是 200 -
from django.test import TestCase,但这不是问题。 -
我虽然您的过滤器工作正常,但在您更新问题后,我认为您应该检查您的过滤器集而不是创建一个新函数。您可以打印 sql 查询,以便我们现在可能会导致问题,如果您可以将模型包含到问题中,那就太好了。现在我认为问题是您的过滤器没有返回任何数据,这个问题与
ReadOnlyModelViewSet无关,我认为
标签: django rest filter django-rest-framework