Showing a related fields attribute - django

How would I do this to show the ForeignKey protected_area's name field?:
class NotificationReceiverSerializer(serializers.ModelSerializer):
class Meta:
model = NotificationReceiver
fields = ('pk','cellphone', 'protected_area__name')
So now its just showing as PK, as expected:
protected_area":1

Try something like this.
class NotificationReceiverSerializer(serializers.ModelSerializer):
proteced_area = serializers.ReadOnlyField(source="protected_area.name")
class Meta:
model = NotificationReceiver
fields = ('pk','cellphone', 'protected_area')
This will show the protected_area names as a read only field. Alternatively,
class NotificationReceiverSerializer(serializers.ModelSerializer):
proteced_area = ProtectedAreaSerializer(read_only=True, many=True)
class Meta:
model = NotificationReceiver
fields = ('pk','cellphone', 'protected_area')
to show all the fields in the related model

Related

django-rest ModelSerializer select fields to display in nested relationship

I'm going to reference the django-rest-framework API example on this. Lets say we have two serializers defined as below.
class TrackSerializer(serializers.ModelSerializer):
class Meta:
model = Track
fields = ['order', 'title', 'duration']
class AlbumSerializer(serializers.ModelSerializer):
tracks = TrackSerializer(many=True, read_only=True)
class Meta:
model = Album
fields = ['album_name', 'artist', 'tracks']
Now if i do a GET request and retrieve an Album instance, it will return me a response with a list of Track instances inside it where each instance contains all the fields of Track. Is there a way to return only a selected subset of the fields in the Track model? For example to only return the title and duration field to the client but not the 'order' field.
You can make a specific TrackSerializer for your Album, like:
class TrackSerializer(serializers.ModelSerializer):
class Meta:
model = Track
fields = ['order', 'title', 'duration']
class TrackForAlbumSerializer(serializers.ModelSerializer):
class Meta:
model = Track
fields = ['title', 'duration']
class AlbumSerializer(serializers.ModelSerializer):
tracks = TrackForAlbumSerializer(many=True, read_only=True)
class Meta:
model = Album
fields = ['album_name', 'artist', 'tracks']
You do not have to define a single serializer per model, you can define multiple serializers you each use for a dedicated task.

Django_Rest_Framework Serializer Field "source" attribute is not working

I am trying to build a DRF Serializer that uses different names for the fields than the underlying Django Model. I thought that this is what the "source" attribute was for.
Here is some code:
models.py:
class MyModel(models.Model):
my_snake_case_field = models.DateTimeField()
serializers.py:
class MySerializer(serializers.ModelSerializer):
class Meta:
model = MyModel
fields = ('id', 'myCamelCaseField', )
myCamelCaseField = serializers.DateTimeField(source='my_snake_case_field')
But when I try to view that I get the following error:
ImproperlyConfigured at /api/mymodel/1/ Field name myCamelCaseField
is not valid for model MyModel.
Any ideas where I'm going wrong?
It might be a Indentation error, It should not inside the Meta class
class MySerializer(serializers.ModelSerializer):
myCamelCaseField = serializers.DateTimeField(source='my_snake_case_field')
class Meta:
model = MyModel
fields = ('id', 'myCamelCaseField',)
Try this for instance:
Now you've assigned myCamelCaseField before calling it.
class MySerializer(serializers.ModelSerializer):
myCamelCaseField = serializers.DateTimeField(source='my_snake_case_field')
class Meta:
model = MyModel
fields = ('id', 'myCamelCaseField', )

Serialization of child models

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

djangrestframework to display model in foreign key

Please excuse the title. Im not quite sure how ask this question without just showing.
In django I have two models.
class people(models.Model):
name=models.TextField(max_length=100)
nickname=models.TextField(max_length=100)
class visits(models.Model):
person=models.OneToOneField(people)
visitdate=models.DateTimeField(auto_now=True)
and then a serializer for the restapi.
#serializers.py
class VisitsSerializer(serializers.ModelSerializer):
class Meta:
model = visits
fields=("id","person","date")
When the API returns the dictionary, it looks like this.
{id:1,person:1,visitdate:11/23/17}
Is there a way to make the API return the actual values that are associated with the person with id 1? like so.
{id:1,person:{id:1,name:foo,nickname:bar},visitdate:11/23/17}
Try creating a serializer class for People and then add this to your visit serializer:
people = PeopleSerializer(read_only = True)
then add it(people) to fields in the Meta class, and just a suggestion, try making it a foreign key instead of a OnetoOne Relationship
You can do that with nested relationship. Here is an example:
class PersonSerializer(serializers.ModelSerializer):
class Meta:
model = people
fields = ('name', 'nickname')
class VisitsSerializer(serializers.ModelSerializer):
person = PersonSerializer(read_only=True)
class Meta:
model = visits
fields = ("id", "person", "date")
Documentation on nested serializers is here.
The Corresponding Serializer would be as follows:
class PersonSerializer(serializers.ModelSerializer):
class Meta:
model = people
class VisitsSerializer(serializers.ModelSerializer):
person = serializers.SerializerMethodField()
class Meta:
model = visits
fields = ('id', 'person', 'date')
def get_person(self, obj):
return PersonSerializer(obj.person).data

django use model choices in modelform

I was wondering how i should use my model choices options, in my ModelForm.
Example(model):
class NPCGuild(models.Model):
CATEGORIES=(
('COM', 'Combat'),
('CRA', 'Crafting'),
('WAR', 'Warfare'),
)
faction = models.ForeignKey(Faction)
category = models.CharField(max_length=3, choices=CATEGORIES)
name = models.CharField(max_length=63)
My Form:
class NPCGuildForm(forms.ModelForm):
name = forms.CharField()
category = forms.CharField(
some widget?)
faction_set = Faction.objects.all()
faction = forms.ModelChoiceField(queryset=faction_set, empty_label="Faction", required=True)
class Meta:
model = NPCGuild
fields = ['name', 'category', 'faction']
As you can see, im not sure what i should be doing to get my choices from my model as a choicefield. Maybe it can be done with a ModelChoiceField as well, but then how to get the choices in it?
You should specify model in the Meta class and fields will be generated automatically:
class NPCGuildForm(forms.ModelForm):
class Meta:
model = NPCGuild
You can add extra form fields if you want to. Read more about ModelFroms.
Update As karthikr mentioned in the comment. If you want to set available choices in a form field, you have to use forms.ChoiceField, like this:
category = forms.ChoiceField(choices=NPCGuild.CATEGORIES)
I will do it differently, just keep in mind that you can generate the whole form from the model automatically, without having to create each field again, and this is one of the beauty of Django which save you time, here is how I will do it, in your form file:
class NPCGuildForm(forms.ModelForm):
class Meta:
model = NPCGuild
fields = ['name', 'category', 'faction']
widgets = {
'category' : forms.Select()
}