6π
I would suggest keeping category specific data separate (in details page) and only having a products API.
For getting products under a certain category, you could do something like β
views.py
from django.shortcuts import get_object_or_404
from oscar.core.loading import get_model
from rest_framework import generics
from oscarapi.serializers import ProductsSerializer
Category = get_model('catalogue', 'Category')
Product = get_model('catalogue', 'Product')
class CategoryProductsView(generics.ListAPIView):
serializer_class = ProductsSerializer
def get_queryset(self):
cat_id = self.kwargs.get('pk', None)
if cat_id is not None:
category = get_object_or_404(Category, id=cat_id)
return Product.objects.filter(
categories__path__startswith=category.path).all()
else:
return Product.objects.none()
urls.py
from views import CategoryProductsView
urlpatterns = [
...
url(r'^caty/(?P<pk>[0-9]+)/products/$', CategoryProducts.as_view(), name='category-products'),
...
]
Since we are using categories__path__startswith
weβd get all products under that category, including those under the subcategory of given category, and so on.
Update
As for the subcategories you want listed, you could simply add a SerializerMethodField()
to do that for you. Iβd suggest getting a list of ids for the subcategories so that further fetching the details of that subcategory would be easier given itβs id (simple lookup from the existing list of categories)
serializers.py
from oscarapi.utils import OscarModelSerializer
from rest_framework import serializers
class CategorySerializer(OscarModelSerializer):
subcategories = serializers.SerializerMethodField()
class Meta:
model = Category
fields = ('id', 'numchild', 'name', 'description', 'image', 'slug',
'path', 'depth', 'subcategories')
def get_subcategories(self, obj):
return Category.objects.filter(path__startswith=obj.path,
depth=obj.depth+1
).values_list('id', flat=True)
sample output
"results": [
{
"id": 1,
"numchild": 1,
"name": "Cat1",
"description": "",
"image": "http://localhost:8001/media/categories/images/categories/cat1.jpg",
"slug": "cat1",
"path": "0001",
"depth": 1,
"subcategories": [
2
]
},
{
"id": 2,
"numchild": 0,
"name": "SubCat1",
"description": "",
"image": null,
"slug": "subcat1",
"path": "00010001",
"depth": 2,
"subcategories": [
]
},
]
1π
django-oscar
uses django-treebeard
for a materialized path implementation, pretty much the opposite of the nested hierarchy you want to retrieve.
I have no experience in writing serializers along with treebeard, but i am pretty sure that you will need to rewrite your Serializer to something like
# Get all categories from /caty
class CategorySerializer(serializers.ModelSerializer):
children = serializers.SerializerMethodField('get_children')
def get_children(self, obj):
if obj.numchild == 0:
return None
# Use treebeards built-in tree generation
[CategorySerializer(child) for child in Category.get_tree(obj)]
class Meta:
model = Category
Notice that i have NOT tested any of this, i am just trying to point you in a direction that might bring you closer to a solution.
- Convert python datetime with timezone to string
- Django application 504 error after saving model
- Passing an object created with SubFactory and LazyAttribute to a RelatedFactory in factory_boy
- All the values of the many to many field : Django