2

I have Model with dictionary object, in below example want to set and get daily availability example

Currently I am able to read, want to make this to read and write, what should I do for this

        "teacher_date": [
            {
                "day_available": "MON",
                "time_available": "Morning"
            },
            {
                "day_available": "SAT",
                "time_available": "Afternoon"
            },
            {
                "day_available": "SUN",
                "time_available": "Evening"
            }

Here is my model.py


class Availability(models.Model):
    uid = models.AutoField(verbose_name='ID', 
                                  serialize=False, 
                                  auto_created=True, 
                                  primary_key=True)
    MONDAY = 'MON'
    TUESDAY = 'TUE'
    WEDNESDAY = "WED"
    THURSDAY = "THU"
    FRIDAY = 'FRI'
    SATURDAY = "SAT"
    SUNDAY = "SUN"
    DAY = (
        (MONDAY, 'Monday'),
        (TUESDAY, 'Tuesday'),
        (WEDNESDAY, 'Wednesday'),
        (THURSDAY, 'Thursday'),
        (FRIDAY, 'Friday'),
        (SATURDAY, 'Saturday'),
        (SUNDAY, 'Sunday'),
    )
    day_available = models.CharField(
        max_length=3, choices=DAY, default=MONDAY)

    MORNING = 'Morning'
    NOON = 'AfterNoon'
    EVENING = 'Evening'
    TIME = (
        (MORNING, 'Morning'),
        (NOON, 'Afternoon'),
        (EVENING, 'Evening'),
    )

    time_available = models.CharField(
        max_length=30, choices=TIME, default=MORNING)

    def __str__(self):
        return f"{self.day_available} {self.time_available}"


Here is my serializer.py file


class AvailabilityDetails(serializers.ModelSerializer):
    class Meta:
        model = Availability
        fields = ('day_available', 'time_available',)


class TeacherProfileDetails(serializers.ModelSerializer):
    logger = logging.getLogger(__name__)
    teacher_date = AvailabilityDetails(many=True, read_only=True)
    first_name = serializers.CharField(source='user.first_name', read_only=True)
    last_name = serializers.CharField(source='user.last_name', read_only=True)
    cities = serializers.SlugRelatedField(many=True, slug_field='city', queryset=City.objects.all(),)
    subject = serializers.SlugRelatedField(many=True, slug_field='subject', queryset=Subject.objects.all(),)
    teacher_date = AvailabilityDetails(many=True, read_only=True)
    user = UserDetailsSerializer(read_only=True)

    class Meta:
        model = Teacher
        fields = ('user', 'first_name', 'last_name', 
                  'bio', 'teacher_cost', 'subject', 'teacher_date', 'cities')

    def get_subject(self, obj):
        subject_list = []
        for i in obj.subject.all():
            subject_list.append(i.subject)
        return subject_list

Here is my **views.py**

class TeacherListCreateAPIView(APIView):
        logger = logging.getLogger(__name__)

        #def create(self, request, *args, **kwargs):
        def get(self, request, *args, **kwargs):
            self.logger.info("Geeting TeacherListCreateAPIView information")
            teacherList = Teacher.objects.filter(user__username=kwargs["username"])
            self.logger.info(teacherList)
            serializers = TeacherProfileDetails(teacherList, many=True)
            self.logger.info(serializers.data)
            return Response(serializers.data)
        def patch(self, request, *args, **kwargs):
            teacher = Teacher.objects.get(user__username=kwargs['username'])
            serializers = TeacherProfileDetails(data=request.data, instance=teacher)
            self.logger.info(serializers)
            if serializers.is_valid():
                serializers.save()
                return Response(serializers.data, status=status.HTTP_201_CREATED)
            return Response(serializers.errors, status=status.HTTP_400_BAD_REQUEST)

What kind of serialization should be done on teacher_date to perform write operation also ?

1 Answers1

0

Problem lies in the way you have defined your serializer.

You have defined teacher_date as read_only field. Hence, this field will be ignored in PUT/POST call.

teacher_date = AvailabilityDetails(many=True, read_only=True)

Refer this https://www.django-rest-framework.org/api-guide/fields/#read_only

asad_hussain
  • 1,959
  • 1
  • 17
  • 27
  • I tried to remove read_only=True, then getting below error ` AssertionError: The `.update()` method does not support writable nested fields by default. Write an explicit `.update()` method for serializer `apis.serializers.TeacherProfileDetails`, or set `read_only=True` on nested serializer fields. ` – Rayees Namathponnan Jan 20 '20 at 07:20
  • According to your use case, the below post provides 2 solutions. You can go with either of them. https://stackoverflow.com/a/41313121/5889270 – asad_hussain Jan 20 '20 at 07:26
  • My usecase different from the one you mentioned above, I have dictionary two key value pair in each branch ``` "teacher_date": [ { "day_available": "MON", "time_available": "Morning" }, { "day_available": "SAT", "time_available": "Afternoon" }, { "day_available": "SUN", "time_available": "Evening" } ``` – Rayees Namathponnan Jan 20 '20 at 07:57
  • Inside your patch of view class, get the DB object for the Availability model using the key related to Availability i am assuming to be present in request.data, then pass that DB object in save() of your serializer. – asad_hussain Jan 20 '20 at 08:41
  • Inside the Patch I can get the teacher object, more how is possible to update one field in patch method ? – Rayees Namathponnan Jan 20 '20 at 15:32