У меня проблема с 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
не работает, но код дает хороший результат с объектами фильтров. Мои URL:
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])