title: Django Rest Framework - How to nest several fields in a serializer?
body: <p>I have several a base model with several control fields. Among them a location fields compound from lat, lon, accuracy, provider and client time. Most of my writable models (and hence resources) are inheriting from this base model. </p>
  
  <p>I'm trying to make DRF serialize the location related fields in a nested "location" field. For example, </p>
  
  <pre><code>{
   "id": 1, 
   "name": "Some name",
   "location": { 
     "lat": 35.234234, 
     "lon": 35.234234,
     "provider": "network", 
     "accuracy": 9.4, 
   }
  }
  </code></pre>
  
  <p>I'ts important to remember that these fields are regular (flat) fields on the base model. </p>
  
  <p>I've investigated and found several options</p>
  
  <ol>
  <li><p>Create a custom field and by overriding "get_attribute" create the nested representation. I don't like this solution because i lose some of the benefits of the model serializer such as validation. </p></li>
  <li><p>Create a nested resource called Location. I guess i could make it work by adding a property by the same name on the model but again, no validations.</p></li>
  </ol>
  
  <p>So my question is, <strong>What is the best way to nest ( or group ) several fields in a DRF serializer ?</strong></p>
  
  <p>DRF 3.0.0, Django 1.7</p>
  
  <p>EDIT: </p>
  
  <p>Building on top of @Tom Christie answer this is what i came up with (simplified)</p>
  
  <pre><code># models.py
  class BaseModel(models.Model):
    id = models.AutoField(primary_key=True)
    lat = models.FloatField(blank=True, null=True)
    lon = models.FloatField(blank=True, null=True)
    location_time = models.DateTimeField(blank=True, null=True)
    location_accuracy = models.FloatField(blank=True, null=True)
    location_provider = models.CharField(max_length=50, blank=True, null=True)
  
    @property
    def location(self):
      return {
        'lat': self.lat,
        'lon': self.lon,
        'location_time': self.location_time,
        'location_accuracy': self.location_accuracy,
        'location_provider': self.location_provider
      }
  
  class ChildModel(BaseModel):
    name = models.CharField(max_lengtg=10)
  
  
  # serializers.py
  class LocationSerializer(serializers.Serializer):
    lat = serializers.FloatField(allow_null=True, required=False)
    lon = serializers.FloatField(allow_null=True, required=False)
    location_time = serializers.DateTimeField(allow_null=True, required=False)
    location_accuracy = serializers.FloatField(allow_null=True, required=False)
    location_provider = serializers.CharField(max_length=50,allow_null=True, required=False)
  
  
  class BaseSerializer(serializers.ModelSerializer):
  
    def create(self,validated_data):
      validated_data.update(validated_data.pop('location',{}))
      return super(BaseSerializer,self).create(validated_data)
  
    def update(self, instance, validated_data):
      location = LocationSerializer(data=validated_data.pop('location',{}), partial=True)
      if location.is_valid():
        for attr,value in location.validated_data.iteritems():
          setattr(instance,attr,value)
      return super(BaseSerializer,self).update(instance, validated_data)
  
  class ChildSerializer(BaseSerializer):
      location = LocationSerializer()
  
      class meta:
        model = ChildModel
        fields = ('name','location',)
  </code></pre>
  
  <p>I've tested with valid/invalid post/patch and it worked perfectly. </p>
  
  <p>Thanks. </p>