Sneaky Toes
Sneaky Toes

Reputation: 107

Django Restful: Nested Serializers

I'm adding a 'tests' field to my 'Sample' model, where 'tests' will be a list of 'TestRequest' objects. Currently, I'm getting this error:

Got AttributeError when attempting to get a value for field `tests` on serializer `SampleSerializer`.
The serializer field might be named incorrectly and not match any attribute or key on the `Sample` instance.
Original exception text was: 'Sample' object has no attribute 'tests'.

'tests' is not a field on my model. I'm just trying to add it to the serialized data. Currently, I can get a nested serializer to work for 'klass' but that is because it's defined in the model.

Models:

class Sample(models.Model):
    name = models.CharField(max_length=50, null=False, blank=False)
    comments = models.TextField(null=True, blank=True)
    klass = models.ForeignKey('samples.Batch', null=True, blank=True,
        related_name='samples', verbose_name='Batch')
    product = models.ForeignKey('customers.Product', blank=False)

    NOTRECEIVED = 'nr'
    RECEIVED = 'rc'
    DISCARDED = 'dc'
    DEPLETED = 'dp'

    SAMPLE_STATUS = (
        (NOTRECEIVED, 'not received'),
        (RECEIVED, 'received'),
        (DISCARDED, 'discarded'),
        (DEPLETED, 'depleted'),
    )

    status = models.CharField(
        max_length=2, choices=SAMPLE_STATUS, default=NOTRECEIVED)
    is_recycling = models.BooleanField(default=False)
    is_submitted = models.BooleanField(default=False)

    received_date = models.DateTimeField(
        _('date received'), null=True, blank=True)


class TestRequest(models.Model):
        client = models.ForeignKey('customers.Client')
        company = models.ForeignKey('customers.Company')
        sample = models.ForeignKey('samples.Sample')
        procedure_version = models.ForeignKey('registery.ProcedureVersion')
        replicates = models.PositiveIntegerField(editable=True, null=True, blank=True)
        created_date = models.DateTimeField('Date created', auto_now_add=True)
        last_updated = models.DateTimeField(auto_now=True)
        comments = models.TextField('Comments', blank=True)

Serializers:

class TestSerializer(serializers.ModelSerializer):
    href = serializers.HyperlinkedIdentityField(lookup_field='pk', lookup_url_kwarg='pk', read_only=True, view_name='samples_api:test-detail')

    class Meta:
        model = TestRequest
        fields = ('id', 'href',)

class SampleBatchSerializer(serializers.ModelSerializer):
    href = serializers.HyperlinkedIdentityField(
        lookup_field='pk', lookup_url_kwarg='batch_pk', read_only=True, view_name='samples_api:batch-detail')

    class Meta:
        model = Batch
        fields = ('id', 'href',)

class SampleSerializer(serializers.ModelSerializer):
    tests = TestSerializer(many=True)
    klass = SampleBatchSerializer(many=False)

    class Meta:
        model = Sample
        # list_serializer_class = FilteredListSerializer
        fields = ('id', 'name', 'tests', 'klass',)

    def create(self, validated_data):
        ...

    def update(self, instance, validated_data):
        ...

Viewsets:

class TestRequestViewSet(viewsets.ModelViewSet):
    """
    Viewset for the TestRequest model
    """
    serializer_class = TestRequestSerializer

    def get_queryset(self):
        client = get_object_or_404(Client, user=self.request.user)
        return TestRequest.objects.filter(company=client.company)

    def perform_create(self, serializer):
        # Override default creatation to provide request based information.
        client = get_object_or_404(Client, user=self.request.user)
        company = client.company
        serializer.save(client=client, company=company)

class SampleViewSet(viewsets.ModelViewSet):
    """
    Viewset for the Sample model
    """
    serializer_class = SampleSerializer

    def get_queryset(self):
        client = get_object_or_404(Client, user=self.request.user)
        return Sample.objects.filter(klass__company=client.company)

I would rather not have to add the field to the model. A 'Sample' can have many 'TestRequest's but a 'TestRequest' can only have one 'Sample'.

How do I get my serializer to add the 'tests' field that isn't in the model?

Upvotes: 0

Views: 445

Answers (1)

Amrit
Amrit

Reputation: 2165

in your SampleSerializer. You have specified 'tests' which is not in your Sample class in your model...

Use nested SerializerMethodField as below....

tests = serializers.SerializerMethodField()

def get_tests(self, obj):

    var=TestRequestSerializer(obj.id)
     return var.data

Upvotes: 1

Related Questions