2

My models are:

class User(models.Model):
    id = models.AutoField(primary_key=True)
    email = models.EmailField()


class Lawyer(models.Model):    
    user = models.OnetoOneField(User)


class Session(models.Model):
    name = models.CharField()
    lawyer = models.ForeignKey(Lawyer)

I am trying to create multiple objects with a list serializer for Session.
From the app side they don't have the id of lawyer, but have the email of each lawyer. How can I write a list serializer where I can take the following json input and use email to fetch lawyer to store multiple session objects?

The json input sent will be like:

[
    {
        "name": "sess1",
        "email": "lawyer1@gmail.com",
    },
    {
        "name": "sess1",
        "email": "lawyer1@gmail.com",
    }
]
cezar
  • 11,616
  • 6
  • 48
  • 84
Jiss Raphel
  • 365
  • 4
  • 15
  • 1
    Both entries in your JSON example are identical. Is this intended or a mistake? The `Session` attribute `name` is not set to be uniqe. The same is valid for `email` in `User`. Should those values be unique? – cezar Aug 23 '18 at 07:55
  • This [answer](https://stackoverflow.com/a/33063111/3848833) might help you. – cezar Aug 23 '18 at 07:58
  • Here is another useful [answer](https://stackoverflow.com/a/45610179/3848833). – cezar Aug 23 '18 at 08:05

2 Answers2

3

You can do it in this way but I think email should be unique=True.

Then use a serializer like this:

from django.utils.translation import ugettext_lazy as _

class SessionCreateManySerializer(serializers.ModelSerializer):
    email = serializers.SlugRelatedField(
        source='lawyer',
        slug_field='user__email',
        queryset=Lawyer.objects.all(),
        write_only=True,
        error_messages={"does_not_exist": _('lawyer with email={value} does not exist.')}
)

    class Meta:
        model = Session
        fields = ('name', 'email')

and a generic create view (just override get_serializer and place many=True in kwargs ):

from rest_framework.response import Response
from rest_framework import generics

class SessionCreateManyView(generics.CreateAPIView):
    serializer_class = SessionCreateManySerializer

    def get_serializer(self, *args, **kwargs):
        kwargs['many'] = True
        return super(SessionCreateManyView, self).get_serializer(*args, **kwargs)
Ehsan Nouri
  • 1,990
  • 11
  • 17
2

You can use bulk creation as well:

# serializers.py
from myapp.models import Session
from rest_framework import serializers


class SessionSerializer(serializers.Serializer):
    email = serializers.EmailField(required=True)
    name = serializers.CharField(required=True)

    def validate_email(self, email):
        lawyer = Lawyer.objects.filter(user__email=email).first()

        if not lawyer:
            raise ValidationError(detail="user dose not exist.")

        return lawyer

    def create(self, validated_data):
        return Session.objects.create(name=validated_data.get('name'), lawyer=validated_data.get('email'))

and in your api.py file allow bulk creation:

# api.py
from rest_framework import generics

class SessionCreateAPIView(generics.CreateAPIView):
    """Allows bulk creation of a resource."""
    def get_serializer(self, *args, **kwargs):
        if isinstance(kwargs.get('data', {}), list):
            kwargs['many'] = True

        return super().get_serializer(*args, **kwargs)