So when I am routing to api/ to view my models I am not seeing what I expected to see.
I wanted to see the names of the strats that I grouped in Strat_Basket model in the variable basket but instead I see their ids which is generated by DJANGO automatically.
I want to see the names rather than numbers in the strat_basket view. It is more informative that's why.
models.py
class Strats(models.Model):
name = models.CharField(max_length=64)
class Strats_Basket(models.Model):
name = models.CharField(max_length=64)
basket = models.ManyToManyField(Strats, blank=True, related_name='list')
serializers.py:
class StratsSerializer(serializers.ModelSerializer):
class Meta:
model = Strats
fields = ('id', 'name')
class Strats_BasketSerializer(serializers.ModelSerializer):
class Meta:
model = Strats_Basket
fields = ('id', 'name', 'basket')
views.py:
class StratsView(viewsets.ModelViewSet):
serializer_class = StratsSerializer
queryset = Strats.objects.all()
class Strats_BasketView(viewsets.ModelViewSet):
serializer_class = Strats_BasketSerializer
queryset = Strats_Basket.objects.all()
urls.py:
router = routers.DefaultRouter()
router.register(r'strats', views.StratsView, 'strats')
router.register(r'strats_basket', views.Strats_BasketView, 'strats_basket')
API OUTPUT:
strats:
[
{
"id": 1,
"name": "strat1"
},
{
"id": 2,
"name": "strat2"
},
{
"id": 3,
"name": "strat3"
},
{
"id": 4,
"name": "strat4"
},
{
"id": 5,
"name": "strat5"
},
{
"id": 6,
"name": "strat6"
}
]
strats_basket:
Instead of 1,2,4 I want to see strat1, strat2, strat4.
[
{
"id": 1,
"name": "Basket 1",
"basket": [
1,
2,
4
]
},
{
"id": 2,
"name": "Basket 2",
"basket": [
3,
5,
6
]
}
]
You can use SerializerMethodField and inside the method return names list using values_list with flat=True
class Strats_BasketSerializer(serializers.ModelSerializer):
basket = serializers.SerializerMethodField()
def get_basket(self, obj):
return obj.basket.all().values_list('name', flat=True)
class Meta:
model = Strats_Basket
fields = ('id', 'name', 'basket')
Related
I have UserModel each user has multiple package and each package have price and program.
model.py:
class User(models.Model):
name= models.CharField(max_length=100)
class Package(models.Model):
package_name = models.CharField(max_length=100)
user= models.ForeignKey(User, on_delete=models.CASCADE,related_name='user_package')
class Program(models.Model):
title = models.CharField(max_length=100)
user_package = models.ForeignKey(Package, on_delete=models.CASCADE)
class Price(models.Model):
price = models.FloatField()
user_package = models.ForeignKey(Package, on_delete=models.CASCADE)
serializer look like:
class UserSerializer(NestedCreateMixin, NestedUpdateMixin,serializers.ModelSerializer):
program = ProgramSerializer(source='user_program', many=True, read_only=True)
package = PackageSerializer(source='user_package', many=True, read_only=True)
price = PriceSerializer(source='price', many=True, read_only=True)
class Meta:
model = User
fields= ("__all__")
views.py:
class user_apiView(APIView):
def get(self, request):
user= user.objects.all()
serializer = UserSerializer(user, many = True)
return Response(serializer.data)
and that what I get:
{
"id": 1,
"package": [
{
"id": 1,
"package_name": "wfe",
"user": 1
},
{
"id": 2,
"package_name": "wfe",
"user": 1
}
]
}
how can GET this RESULT?
{
"id": 1,
"package": [
{
"id": 1,
"package_name": "wfe",
"user": 1
},
{
"id": 2,
"package_name": "wfe",
"user": 1
}
],
"price": [
{
"id": 1,
"price": "wfe",
"package": 1
},
{
"id": 2,
"price": "wfe",
"package": 2
}
]
"program": [
{
"id": 1,
"title": "wfe",
"package": 1
},
{
"id": 2,
"title": "wfe",
"package": 2
}
]
}
The problem is that your price and program models are not directly related to your user model. If you consider the relations it is like price -> package -> user, so you will have to get those relations in the package serializer instead like this
serializers.py
class ProgramSerializer(serializers.ModelSerializer):
class Meta:
model = Program
fields= ("__all__")
class PriceSerializer(serializers.ModelSerializer):
class Meta:
model = Price
fields= ("__all__")
class PackageSerializer(serializers.ModelSerializer):
program = ProgramSerializer(source='program_set', many=True, read_only=True)
price = PriceSerializer(source='price_set', many=True, read_only=True)
class Meta:
model = Package
fields= ("__all__")
class UserSerializer(serializers.ModelSerializer):
package = PackageSerializer(source='user_package', many=True, read_only=True)
class Meta:
model = User
fields= ("__all__")
Note that this will however not give you the output in the format you mentioned though, the price and program fields will instead be nested under package.
[
{
"id": 1,
"package": [
{
"id": 1,
"program": [
{
"id": 1,
"title": "program1",
"user_package": 1
}
],
"price": [
{
"id": 1,
"price": 1000.0,
"user_package": 1
}
],
"package_name": "package1",
"user": 1
},
{
"id": 2,
"program": [
{
"id": 2,
"title": "program2",
"user_package": 2
}
],
"price": [
{
"id": 2,
"price": 1500.0,
"user_package": 2
}
],
"package_name": "package2",
"user": 1
}
],
"name": "user1"
}
]
If you really want the format in the way you posted you might instead want to take a look at https://www.django-rest-framework.org/api-guide/fields/#serializermethodfield
I have my models.py as shown below:
from django.db import models
# Create your models here.
class Category(models.Model):
categoryType = models.CharField(max_length=100,blank = False, unique = True, null = False)
def __str__(self):
return self.categoryType
class SubCategory(models.Model):
subcategoryType = models.CharField(max_length=100)
categoryType = models.ForeignKey(Category,on_delete=models.CASCADE, null = True, related_name='category_type')
def __str__(self):
return f'{self.categoryType} :: {self.subcategoryType}'
class Product(models.Model):
productName = models.CharField(max_length=50,blank = False, null = False)
subCategoryType = models.ForeignKey(SubCategory,on_delete=models.SET_NULL, null=True,related_name='product_subcategories')
#categoryType = models.ForeignKey(Category,on_delete=models.SET_NULL, null=True,related_name='product_categories')
def __str__(self):
return f'{self.productName} : {self.subcategoryType}'
I have created a serializer to get all products within a given category as shown below:
class ProductSerializerSpecific(serializers.ModelSerializer):
class Meta:
model = Product
fields = ('id','productName')
class SubCategoryProductsSpecific(serializers.ModelSerializer):
products = ProductSerializerSpecific(source='product_subcategories', many=True)
class Meta:
model = SubCategory
fields = ['products']
class CategoryProducts(serializers.ModelSerializer):
products = SubCategoryProductsSpecific(source='category_type', many=True)
class Meta:
model = Category
fields = ('id','products')
My View goes like this:
class ListAllCategoryProducts(viewsets.ReadOnlyModelViewSet):
queryset = Category.objects.all()
serializer_class = CategoryProducts
And finally I registered by route like this:
router.register(r"category_products", views.ListAllCategoryProducts, basename="categories_products")
When I do a GET request to get all products with a given ID as shown below:
GET http://localhost:8000/category_products/1 HTTP/1.1
The output comes as shown below:
{
"id": 1,
"products": [
{
"products": []
},
{
"products": []
},
{
"products": []
},
{
"products": [
{
"id": 1,
"productName": "Dell XPS"
},
{
"id": 2,
"productName": "Macbook Pro"
},
{
"id": 3,
"productName": "Dell Inspiron"
},
{
"id": 4,
"productName": "Lenevo Ideapad"
},
{
"id": 5,
"productName": "Asus"
}
]
}
]
}
Where each dictionary inside list represents the subcategory, but I was interested in getting a result which had just products which would look something like this:
{
"id": 1,
"products": [
{
"id": 1,
"productName": "Dell XPS"
},
{
"id": 2,
"productName": "Macbook Pro"
},
{
"id": 3,
"productName": "Dell Inspiron"
},
{
"id": 4,
"productName": "Lenevo Ideapad"
},
{
"id": 5,
"productName": "Asus"
}
]
}
If you observe carefully the result I am getting basically is category => subcategory => products, whereas I am interested in category => products (where subcategory is fetched from category and products are fetched from subcategory). What should be the way to do the same? Since products aren't directly linked with category rather they need to go via sub category.
In the Category model, we can make a property to return the QuerySet of all related Products with:
class Category(models.Model):
categoryType = models.CharField(max_length=100,blank = False, unique = True, null = False)
#property
def products(self):
return Product.objects.filter(subCategoryType__categoryType=self)
def __str__(self):
return self.categoryType
Then we remove the SubCategoryProductsSpecific serializer in between, this is the item that makes sublists in the response. We can then set the source to:
class ProductSerializerSpecific(serializers.ModelSerializer):
class Meta:
model = Product
fields = ('id','productName')
class CategoryProducts(serializers.ModelSerializer):
products = ProductSerializerSpecific(many=True, read_only=True)
class Meta:
model = Category
fields = ('id', 'products')
I have a Django model as follows:
class Team(models.Model):
name = models.CharField(max_length=100, unique=True)
managers = models.ManyToManyField(User, through=MgrToTeam, related_name='mng')
users = models.ManyToManyField(User, through=UsrToTeam,related_name='usr')
I now have a serializer where i need to display all the users and managers associated with a team:
class TeamDetailSerializer(serializers.ModelSerializer):
managers = serializers.SlugRelatedField(queryset=User.objects.all(), slug_field='name')
users = serializers.SlugRelatedField(queryset=User.objects.all(), slug_field='name')
class Meta:
model = Team
fields = ['id', 'name', 'managers', 'users']
However, this gives me the same output for both the users and managers.How do i fix this ?
I'm curious as to why you want to use a SlugRelatedField. Assuming you do have a UserSerializer of some sort, would it work for you to do it like this?
class TeamDetailSerializer(serializers.ModelSerializer):
managers = UserSerializer(many=True)
users = UserSerializer(many=True)
class Meta:
model = Team
fields = ['id', 'name', 'managers', 'users']
if you just want Just primary key as below
[
{
"id": 1,
"name": "helo",
"users": [
1,
2
],
"managers":[
1,
2,
]
}
]
class TeamDetailSerializer(serializers.ModelSerializer):
class Meta:
model = Team
fields = ['id', 'name', 'users','managers']
if you want return object properties as below
[
{
"id": 1,
"name": "helo",
"users": [
{
"email": "admin#gmail.com",
"first_name": ""
},
{
"email": "admin1#gmail.com",
"first_name": ""
}
],
"managers": [
{
"email": "admin#gmail.com",
"first_name": ""
},
{
"email": "admin1#gmail.com",
"first_name": ""
}
]
}
]
class TeamDetailSerializer(serializers.ModelSerializer):
users = UserDetailSerializer(many=True)
managers = UserDetailSerializer(many=True)
class Meta:
model = Team
fields = ['id', 'name', 'users', 'managers']
I'm trying to return a Response including data from 2 linked models, where I can get a specific field value from another model. The models are:
class Author(models.Model):
author = models.CharField(max_length=200)
author_created = models.DateTimeField(auto_now_add=True)
class Meta:
ordering = ('author_created',)
class Book(models.Model):
book_name = models.CharField(max_length=200)
author_name = models.ForeignKey(Author, on_delete=models.CASCADE)
book_created = models.DateTimeField(auto_now_add=True)
class Meta:
ordering = ('book_created',)
Serializers are:
class AuthorSerializer(serializers.ModelSerializer):
class Meta:
model = Author
fields = ('id', 'author')
class BookSerializer(serializers.ModelSerializer):
name = AuthorSerializer(source='author_name')
class Meta:
model = Book
fields = ('id', 'book_name','name')
My response shows like this:
[
{
"id": 1,
"book_name": "Himu",
"name": {
"id": 1,
"author": "Humayun Ahmed"
}
},
{
"id": 2,
"book_name": "Shanta's family",
"name": {
"id": 2,
"author": "Jafar Iqbal"
}
}
]
But i want to show it like this:
[
{
"id": 1,
"book_name": "Himu",
"name": {
"author": "Humayun Ahmed"
}
},
{
"id": 2,
"book_name": "Shanta's family",
"name": {
"author": "Jafar Iqbal"
}
}
]
How can i get this output?
Try something like this name = AuthorSerializer(source='author_name.author')
Reference : http://www.django-rest-framework.org/api-guide/fields/#source
I'm rather new to Django Rest Framework and I'm trying to use DRF to to serialize a list of (related) objects.
I have the following models:
class Answer(models.Model):
value = models.CharField(max_length=128)
class User(models.Model):
name = models.CharField(max_length=128)
age = models.PositiveIntegerField()
class UserAnswer(models.Model):
user = models.ForeignKey(User)
answer = models.ForeignKey(Answer)
And the result I'm trying to get is in this form:
[
{
"name": "myName1",
"answers": [
{
"value": "myFirstAnswer"
},
{
"value": "mySecondAnswer"
},
{
"value": "myThirdAnswer"
},
]
},
{
"name": "myName2",
"answers": [
{
"value": "myFirstAnswer"
},
{
"value": "mySecondAnswer"
},
{
"value": "myThirdAnswer"
},
]
}
]
I'm trying to do it this way now:
class UserAnswerSerializer(serializers.ModelSerializer):
answers = AllUserAnswersSerializer(many=True, read_only=True)
class Meta:
model = User
fields = ('name', 'answers')
But then I get the following result:
[
{
"name": "myName1"
},
{
"name": "myName2"
}
]
And when I try to do it this way:
class UserAnswerSerializer(serializers.ModelSerializer):
answers = serializers.PrimaryKeyRelatedField(many=True, read_only=True)
class Meta:
model = User
fields = ('name', 'answers')
Then i get the following result (an example again):
[
{
"name": "myName1",
"answers": [
1,
2,
3
]
},
{
"name": "myName2",
"answers": [
4,
5,
6
]
}
]
I'm having a hard time making this work, hope someone can show me how to convert the Primary Key's to actual objects!
Thanks!
Remove the explicit definition of the answers field in your serializer and add depth=1. It should look like this:
class UserAnswerSerializer(serializers.ModelSerializer):
class Meta:
depth = 1
model = User
fields = ('name', 'answers')
Info about depth: http://www.django-rest-framework.org/api-guide/serializers/#specifying-nested-serialization