non trivial django serializer for a complex model

假如想象 提交于 2021-01-29 18:40:51

问题


After many years I code with Java, I got an interesting project at work to be developed using python django rest framework.

I have a complex model, with many relations, in which I want to create entities in DB based on one JSON request. Please refer to attached screenshot of my DB model.

My goal is to create new projects in the DB where I have set of companies in DB and a freelancer can suggest to a project of the company.

I would like to get a JSON request that contains:

  1. company id (ALREADY IN DB)
  2. Freelance: email, name, etc...
  3. Project info: name, year, description -> this will be newly created, unless the name already exists in the DB
  4. List of Tasks
  5. List of Requests

When I get the request on the server, I would like to check first if the freelancer exists (I lookup by email) then use his ID or create a new freelancer entity, then create a new Project entry (I can also check that I don't have duplicate by name and year - in such case throw an error) and create new tasks for the project with the relevant FK and same for Requests.

My experience with JEE, I would simply create a DTO that reflects the JSON and will just have a service layer that checks the condition and creates accordingly the objects.

I am a bit lost how to do it with django, all tutorials I see provide very clear way how to do simple CRUD operations for a DB model that is mapped almost 1 to 1 to the JSON (DTO), there is almost no business logic there.

Could someone please let me know how to get around this? maybe you have any good example you can refer?

Thank you.


回答1:


The individual serializers are used for field validation, so that there is no malicious data.

from django.db import transaction
from rest_framework import serializers

class FreeLancerSerializer(serializers.ModelSerializer):

    class Meta(object):
        model = FreeLancer
        fields = ('email', '...other field')


class TasksSerializer(serializers.ModelSerializer):

    class Meta(object):
        model = Task
        fields = (..task model fields..)


class RequestsSerializer(serializers.ModelSerializer):

    class Meta(object):
        model = Request
        fields = (..request model fields..)


class ProjectSerializer(serializers.ModelSerializer):
    freelancer = FreeLancerSerializer()
    tasks = TasksSerializer(many=True)
    requests = RequestsSerializer(many=True)

    class Meta(object):
        model = Project
        fields = ('project_name', ..project model fields .., 'freelancer', 'tasks', 'requests')

        #project_name validation
        def validate_project_name(self, project_name):
            if Project.objects.filter(project_name=project_name).exists():
                raise serializers.ValidationError("project with this name already exists.")
            return project_name

        @transaction.atomic #will rollback all the transactions if something fails
        def create(self, validated_data):
            freelancer = validated_data.pop('freelancer')
            tasks_data = validated_data.pop('tasks')
            requests_data = validated_data.pop('requests')
            # gets the freelancer if alread created else creates it.
            freelancer_obj = FreeLancer.objects.get_or_create(
                email = freelancer.get('email'),
                defaults = freelancer
            )

            validated_data['freelancer'] = freelancer_obj
            project = super(ProjectSerializer, self).create(validated_data)

            #Validates tasks data and creates tasks
            try:
                task_objects = TasksSerializer(data=tasks_data, many=True)
                task_objects.is_valid(raise_exception=True)
                tasks = task_objects.save()
                project.tasks.add(tasks); #add tasks to project.
            except:
                raise serializers.ValidationError("tasks not valid.")

            #Validates requests data and creates requests
            try:
                request_objects = RequestsSerializer(data=requests_data, many=True)
                request_objects.is_valid(raise_exception=True)
                requests = request_objects.save()
                project.requests.add(requests); #add requests to project.
            except:
                raise serializers.ValidationError("requests not valid.")

            project.save()

            return project

Note : Model level validations will also be needed like email has to be unique for freelancer and name has to be unique project model respectively and so on.

PS : there might be some changes you might need to to do.



来源:https://stackoverflow.com/questions/57599499/non-trivial-django-serializer-for-a-complex-model

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!