django - Django REST api 和 django_filter 问题
问题描述
我有问题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)
我的问题是它print
不起作用get_products
,但代码使用过滤器对象给出了很好的结果。我的网址:
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。
有人知道吗?
感谢马格努斯的任何回答
EDIT
创建了这个函数,就是将好的数据传递给过滤器。
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])
解决方案
您使用的 url 不正确,您应该将此 url 用于您的自定义操作:
/api/shop/get_products/
您正在使用的 url 即/api/shop/将调用视图集的默认列表操作而不是您的自定义操作,这就是为什么您总是得到 200 状态代码
您可以在此处阅读有关视图集的更多信息: ViewSets
推荐阅读
- qt - 如何在 PQT5 的设计器中制作一个可以与其组件一起拉伸的窗口
- c++ - 如何微调/监控 Boost::ODEIt bulirsch stoer?
- java - Servlet 类在我的文件上传程序中不起作用
- reactjs - window.onmessage 在反应 js 组件中不起作用
- r - 忽略日期的月份差异
- javascript - 在 JavaScript 中从文件中加载文本
- swift - 如何更改GraphicalDatePickerStyle日期选择器Swiftui的选择颜色(AM,PM)和时间
- bash - 带或不带双引号的 bash 变量
- javascript - 如何在 JavaScript 中从多个数组中随机选择一个数组
- android - Room:WearOS App 中不再生成数据库文件夹和文件