I have two django models
model A
class A(models.Model):
aname = models.CharField(max_length=64, verbose_name='name')
and model B
class B(models.Model):
bname = models.CharField(max_length=64, verbose_name='name')
mod = models.ForeignKey(A, related_name='a_b',null=True,on_delete=models.CASCADE)
The serializer for model B is
class BSerializer(serializers.ModelSerializer):
mod= ASerializer(many=False, read_only=True)
class Meta:
model = B
fields = (','id','bname','mod.aname')
I want the aname field of model A to be accessed with the serializer of model B. Using mod.aname doesn't work. It says
Field name mod.aname is not valid for model B.
How can i do it?
How about this one? using parameter source inside serializers.CharField:
class BSerializer(serializers.ModelSerializer):
mod = serializers.CharField(
source='mod.aname',
read_only=True
)
class Meta:
model = B
fields = ('id','bname','mod')
Use two underscores when referencing fields of related models as a string, like 'mod__aname'.
class HotelSerializer(serializers.ModelSerializer):
mod= ASerializer(many=False, read_only=True)
class Meta:
model = Hotel
fields = ('id','bname','mod__aname')
This should work if ASerializer looks something like this:
class ASerializer(serializers.ModelSerializer):
class Meta:
model = A
fields = '__all__'
Related
A have three models:
class ModelA(models.Model):
some_field = models.ForeignKey(ModelB)
class ModelC(models.Model):
some_field = models.ForeignKey(ModelB)
class ModelB(models.Model):
first_field = models.CharField()
second_field = models.CharField()
I want serialize ModelA and get value from ModelC. How can you do it?
class ModelASerializer(serializers.ModelSerializer):
class Meta:
model = ModelA
fields = ('id', 'some_field', 'here_is_value_from_ModelC'???)
If you want to get fields of modelC from modelA serializer then this code will works.
class ModelCserializer(serializer.ModelSerializer):
class Meta:
model = ModelC
fields = ('some_field',)
class ModelASerializer(serializers.ModelSerializer):
here_is_value_from_ModelC= ModelCserializer(read_only=True)
class Meta:
model = ModelA
fields = ('id', 'some_field', 'here_is_value_from_ModelC')
or
class ModelASerializer(serializers.ModelSerializer):
some_field= serializer.StringRelatedField(many=True)
class Meta:
model = ModelA
fields = ('id', 'some_field', 'some_field')
nested serializer showing null data
from rest_framework import serializers
from .models import PlayerTable, ChildTable
class ChildTableSerializer(serializers.ModelSerializer):
# x= ChildTable.objects.all().values
class Meta:
model = ChildTable
fields = ('season','goals','fk')
# fields =('fk',)
class PlayerTableSerializer(serializers.ModelSerializer):
player_details = ChildTableSerializer(many=True, read_only=True)
class Meta:
model = PlayerTable
fields = ('player_details',)
please help data getting by serializer is null
what is the field 'player-details'? It's not a field on your PlayerTable model. You need to use the name of the related field. In your case since you have a ForeignKey relationship ChildTable --> PlayerTable and you haven't specified the related_name, it's childtable_set. So if you do this it should work:
class PlayerTableSerializer(serializers.ModelSerializer):
childtable_set = ChildTableSerializer(many=True, read_only=True)
class Meta:
model = PlayerTable
fields = ('childtable_set',)
Alternatively, change your models naming to be more aligned with Django conventions:
class PlayerDetail(models.Model):
player = models.ForeignKey(Player, db_column="fk", related_name="player_details", null=True, blank=True, on_delete=models.CASCADE)
...
class Meta:
managed = False
db_table = "child_table"
class Player(models.Model):
name = models.CharField(db_column="player_name", ...)
class Meta:
db_table = "player_table"
then your serializer would work because the relation is player_details. This also has the advantage that when you do details.player you get the player object (now, you have to do details.fk but that actually doesn't return the foreign key value, it returns the Player object). Also your models have more pythonic names (Player not PlayerTable). Your code will be much more readable.
I have models:
class CommonEditor(models.Model):
def __str__(self):
return 'Common Atributes Mask'
class Color(models.Model):
name = models.CharField(max_length=25)
editor = models.ForeignKey(CommonEditor, on_delete=models.PROTECT, null=True)
So I make serialization this way:
class ColorSerializer(serializers.ModelSerializer):
class Meta:
model = Color
fields = '__all__'
class CommonAttributesSerializer(serializers.ModelSerializer):
color = ColorSerializer(many=True, read_only=True)
class Meta:
model = CommonEditor
fields = ('pk', 'color')
And then view:
class CommonAttributeAPIView(generics.ListCreateAPIView):
serializer_class = CommonAttributesSerializer
queryset = CommonEditor.objects.all()
I get only pk of my CommonEditor Model. Why can't i get the full Atributes Mask and how can I fix it? Big thanks!
Default name for reverse foreign key relation is modelname_set or in your case color_set. So try to rename color field to color_set:
class CommonAttributesSerializer(serializers.ModelSerializer):
color_set = ColorSerializer(many=True, read_only=True)
class Meta:
model = CommonEditor
fields = ('pk', 'color_set')
This can also be achieved via SerializerMethodField and can be seen as follow:
class CommonAttributesSerializer(serializers.ModelSerializer):
color = serializers.SerializerMethodField()
class Meta:
model = CommonEditor
fields = ('pk', 'color')
def get_color(self, common_editor):
return ColorSerializer(common_editor.color_set.all(), many=True).data
Documentation: http://www.django-rest-framework.org/api-guide/fields/#serializermethodfield
The CommonAttributesSerializer search for a color attribute in CommonEditor's instance, but it couldn't find. In DRF serializer, a parameter called source will says explicitly where to look for the data. So , change the serializer as below:
class CommonAttributesSerializer(serializers.ModelSerializer):
color = ColorSerializer(many=True, read_only=True, <b>source='color_set'</b>)
class Meta:
model = CommonEditor
fields = ('pk', 'color')
Reference : DRF Fields -source
models.py
class Category(models.Model):
name = models.CharField(max_length=128)
class Product(models.Model):
category = models.ManyToManyField(Category, related_name="category")
name = models.CharField(max_length=128)
class ProductVariation(models.Model):
product = models.ForeignKey(Product, related_name="product")
name = models.CharField(max_length=128)
serializers.py
class ProductVariantSerializer(serializers.HyperlinkedModelSerializer)
class Meta:
model = ProductVariation
fields = (
"name",
)
class CategoryDetailSerializer(serializers.Modelserializer):
product_variant = PromotionVariantSerializer(many=True)
class Meta:
model = Category
fields =(
"name",
"product_variant" #how can i do this
)
here i want to list all the product variant that belongs to the category.
can i do this way or i want to write methods to get the product variant details
You may need to write serializers for Product and ProductVariation models. You can't display the ProductVariation objects right in the Category model serializer, as there is no direct relation between Category and ProductVariation models. But you could try may be using separate nested serializers for Product and ProductVariation models.
class ProductVariantSerializer(serializers.ModelSerializer):
class Meta:
model = ProductVariation
fields = ("name", )
class ProductSerializer(serializers.ModelSerializer):
variants = ProductVariantSerializer(source='product', many=True, read_only=True)
class Meta:
model = Product
fields = ('name', 'variants')
class CategorySerializer(serializers.ModelSerializer):
products = ProductSerializer(source='category', many=True, read_only=True)
class Meta:
model = Category
fields = ('name', 'products')
You could use the CategorySerializer for nested relationships.
Assume I have these models:
ModelA(models.Model):
some_field_a = models.IntegerField()
ModelB(models.Model):
some_field_b = models.IntegerField()
a = models.ForeignKey(ModelA)
ModelC(models.Model):
some_field_c = models.IntegerField()
b = models.ForeignKey(ModelB)
Then in my serializer for ModelC, I have this to access the field some_field_b from ModelB:
class ModelCSerializer(serializers.ModelSerializer):
field_b = serializers.SlugRelatedField(
read_only=True,
source='some_field_b',
slug_field='some_field_b')
field_a = ???
class Meta:
model = ModelC
fields = ('some_field_c', 'field_b', 'field_a')
But what should I add to field_a to retrieve the value of some_field_a, in the same way I'm retrieving the value from some_field_b?
Not sure if I understand your example, but it seems you wish to walk the relation from C -> B -> A and get that value. You can follow the relation in the source argument using dot syntax, much like you would if you were accessing the object directly.
class ModelCSerializer(serializers.ModelSerializer):
field_b = serializers.SlugRelatedField(
read_only=True,
source='b.some_field_b',
slug_field='some_field_b')
field_a = serializers.SlugRelatedField(
read_only=True,
source='b.a.some_field_a',
slug_field='some_field_a')
class Meta:
model = ModelC
fields = ('some_field_c', 'field_b', 'field_a')