Changing the field name when using Django rest framework - django

I'm feeding serialized data from the Django rest framework to a Javascript pivot table on my site. If I have a variable called 'created_on', the DRF uses that as the field name. What I want to display in my pivot table is the label which will be converted to 'Created On'.
As an example, my output from DRF is the following:
[{"created_on": "2016-04-23"}, {"created_on": "2016-05-23"}]
What I want is:
[{"Created on": "2016-04-23"}, {"Created on": "2016-05-23"}]
Is this possible without me overriding the serialization process?

No, its not possible (currently) without overriding the serialization process.
Why it is not possible?
This is because the alternate name which you want to use for created_on contains whitespace and its not possible to define a field in your serializer having whitespaces in it. Also, there is no functionality currently to provide alternate name for a field to be used in serialization process.
Possible Solution:
You can override the to_representation() method of your serializer and there add a Created On key having value equal to the value of created_on key. Then all the serialized objects will contain a key Created On.
class MySerializer(serializers.ModelSerializer):
...
def to_representation(self, obj):
primitive_repr = super(MySerializer, self).to_representation(obj)
primitive_repr['Created On'] = primitive_repr['created_on']
return primitive_repr
What if the alternate name did not contain any whitespaces?
Had the alternate name did not contain any spaces between them, you could then have used SerializerMethodField() with source argument.
You could have done something like:
class MySerializer(serializers.ModelSerializer):
alternate_name = serializers.SerializerMethodField(source='created_on')
class Meta:
model = MyModel
fields = (.., 'alternate_name')

Related

django how to create a serializer ListField that accepts DictField with images values

As the title describes I need to create a Custom serializer ListField that accepts dictionary of string keys and value of Image
Example input:
[ {'1':FirstImage} , {'3',ThirdImage} ]
What I've tried:
customSerializer = serializers.ListField(
child=serializers.DictField(
child=serializers.ImageField(allow_empty_file=True, use_url=False)
)
)
Obviously my serializer doesnt work as it should, anyone have an idea how can I make this work?
Thanks In Advance
Create a separate serializer class and use that in your ListField like this:
class ImageSerializer(serializers.Serializer):
id = serializers.IntegerField()
image = serializers.ImageField(allow_empty_file=True, use_url=False)
class FinalSerializer(serializers.Serializer):
my_field = serializers.ListField(child=ImageSerializer())
I suggest you don't add the child instance arg, as this will validate all the fields in the model table which will in turn increase endpoint latency.
As specified in the doc:
child - A field instance that should be used for validating the objects in the list. If this argument is not provided then objects in the list will not be validated.
You can write your own validator methods (just the relevant ones).

DRF PrimaryRelatedField when write and NestedSerializer when read?

I am using a nested serializer. I need ProfileSerializer to return full related Project object for get requests and consider only id switching (changing current) like with relatedPrimaryField behaiviour for post/put requests on ProfileSerializer. any solutions on how to achieve this ?
class ProfileSerializer(serializers.ModelSerializer):
current = ProjectSerializer()
class Meta:
model = Profile
fields = ('function', 'current')
As Linova mentioned, the easiest way to solve this issue without using a third-party library is to declare two separate fields in your serializer. Your nested serializer current would stay the same, but you would add a new PrimaryKeyRelatedField serializer. The nested serializer should be read only, but the related field would not be read only. I normally name the related field <field>_id by convention.
In GET requests, both the nested serializer and the id field will be returned, but for PUT or POST requests only the <field>_id needs to be specified.
class ProfileSerializer(serializers.ModelSerializer):
current = ProjectSerializer(read_only=True)
current_id = serializers.PrimaryKeyRelatedField(queryset=Projects.objects.all(), source='current')
class Meta:
model = Profile
fields = ('function', 'current', 'current_id')
The most consistent way I usually advice is to mark all the nested serializer (ProjectSerializer in this case) as read_only and add the id field as read_only=False
You'll therefore have consistence between the list/retrieve and creation/updates.

How can I update two models in one serializer in Django Rest Framework?

I have a database schema that has each object of a certain type being stored across two separate tables (one row in each table, different data in each, with a foreign key from one to the other.)
Unfortunately, Django Rest Framework tends to assume that there is a one to one correspondence between serializers and models, which is not true of my case. How should I be approaching this? It seems like the serializer should return the representation of the object which will be the actual HTTP response of the ajax requests, so using two serializers doesn't seem right. I've looked at extending BaseSerializer (which is how I currently plan to implement this if I don't find better solutions), but certain methods take in an instance, which should contain all the data needed to serialize the object, whereas I have two instances relevant.
Any advice would be super appreciated! Thank you.
Writable nested representations section might help you.
You have 2 models ModelA and ModelB. Create your first model's serializer
class ModelASerializer(serializers.ModelSerializer):
class Meta:
model = ModelA
fields = ('fields',..) #
Then in other model's serializer add the first serializer and override the required methods (like create, update). Something like this:
class ModelBSerializer(serializers.ModelSerializer):
# add the serializer for the foreignkey model
model_a = ModelASerializer()
class Meta:
model = ModelB
fields = ('fields',..) #
def create(self, validated_data):
modela_data = validated_data.pop('model_a')
model_b = ModelB.objects.create(**validated_data)
ModelA.objects.create(model_b=model_b, **modela_data)
return model_b
# override update too ..

What is the read/write equivalent of serializers.StringRelatedField?

In Django Rest Framework 3, I want to return the unicode value of a pk relationship, the way you can using a serializer.StringRelatedField, but I need the value to be writable, too. StringRelatedField is read only.
I don't care if the API accepts the pk, or the string value, on the PUT (though accepting the string would be nifty, and would save me grabbing all the pks!). The API just needs to return the unicode string value on the GET.
I'm thinking PrimaryKeyRelatedField might be the way to go, but what does the query look like?
For instance, if the model I want is "Model", and I want Model.name to be serialized, what does this command look like:
name = serializers.PrimaryKeyRelatedField(queryset=Model.objects.get(pk=????))
I'm struggling because I don't know how to get the pk from the serializer object in order to query the related model ...
That's presuming PrimaryKeyRelatedField is what I need, of course. Which may be totally wrong.
Thanks
John
Here are example models as requested, slightly changed for clarity:
class CarModel(models.Model):
name = models.CharField(max_length=100,unique=True)
def __str__(self):
return self.name
class Car(models.Model):
name = models.CharField(max_length=100)
make = models.ForeignKey(CarMake)
car_model = models.ForeignKey(CarModel)
class CarSerializer(serializers.ModelSerializer):
car_model = serializers.StringRelatedField() //like this, but read/write
class Meta:
model = Car
In this example I'm serializing Car, trying to return a string value of CarModel that can be updated with a select dropdown in a form.
If I use different serializers, one for POST that expects the PK and one for everything else that returns the string, the select directive in the form gets very messy.
So, ideally, I just want to be able to POST the string value, and have the API complete the lookup and save the string as a PK.
"I just want to be able to POST the string value, and have the API complete the lookup and save the string as a PK."
That would imply that 'name' should be unique. If it isn't unique then the lookup might return several instances. In the example you currently have 'name' isn't unique, but if it was then you could use...
car_model = serializers.SlugRelatedField(queryset=..., lookup_field='name')
I'm not convinced if that's actually what you want though. The best way to clarify these sorts of questions is typically to forget about the code for a moment, and just focus on a precise description of what you want the input and output representations to look like?...

Django Rest Framework Dictionary Field

I'm using Mongodb with mongoengine as a backend for a API in Django.
The framework I'm using to create the api is Django Rest Framework.
I need to store a dictionary in a field in Mongo and the best I've done when the method post is called is to use a charfield and parse the dictionary in the function restore_object.
There is a better way to achieve this goal?
It's better to create a dict field? I don't know how hard this could be.
Thank you.
edited to show some code, notice that I store the dictionary as a dict (DictField) and it's content could change from one object to other.
my mongoengine model is something like:
class MyDoc(mongoengine.Document):
name = mongoengine.StringField(max_length=200)
context = mongoengine.DictField()
and my serializer something like:
class MyDocSerializer(serializers.Serializer):
name = serializers.CharField(max_length=200)
context = serializers.CharField()
url = serializers.HyperlinkedIdentityField(
view_name="drf:mydoc-detail",)
def __init__(self,*args,**kwargs):
super(MyDocSerializer,self).__init__(*args,**kwargs)
def restore_object(self, attrs, instance=None):
# Parse string to dict
# this is so ugly, notice I had to repace ' for " to
# avoid an error parsing the json
context = JSONParser().parse(
StringIO.StringIO(
attrs['context'].replace("'","\"")
)
)
attrs['context'] = context
if instance is not None:
instance.name = attrs['name']
instance.context = context
return instance
return MyDoc(**attrs)
Rather than deal with the dictionary field in the Serializer's restore_object, you'll probably end up with something slightly cleaner, if instead you use a custom field for the dictionary field, that manages converting between the dictionary representation and internal char based storage.
You'll want to subclass serializers.WritableField and override the to_native() and from_native methods.
Relevant docs here.
Note: WritableField class that was present in version 2.x no longer exists. You should subclass Field and override to_internal_value() if the field supports data input.
Update: As of 3.0.4 you can now use serializers.DictField... http://www.django-rest-framework.org/api-guide/fields/#dictfield