ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • Web Dev Bootcamp TIL Day-50(DRF Serializers / Query Parameters)
    TIL 2022. 6. 24. 22:18
    • Query parameters are a defined set of parameters attached to the end of a url.
      • They are extensions of the URL that are used to help define specific content or actions based on the data being passed.
      • To append query params to the end of a URL, a ‘?’ Is added followed immediately by a query parameter.

    Sending Query Parameters via Postman

    • Let's say we want to search for jobs posts that require certain skills using query parameters:
      • First, let's make sure that skillsets and job posts are in a many-to-many relationship
      • Notice that we can use an intermediate table to manage the relationship betwen the two models:
    class SkillSet(models.Model):
        name = models.CharField(max_length=128)
        job_posts = models.ManyToManyField('JobPost', through='JobPostSkillSet')
    
        class Meta:
            db_table = 'skill_sets'
    
    class JobPostSkillSet(models.Model):
        skill_set = models.ForeignKey('SkillSet', on_delete=models.SET_NULL, null=True)
        job_post = models.ForeignKey('JobPost', on_delete=models.SET_NULL, null=True)
    
    class JobPost(models.Model):
        job_type = models.ForeignKey(JobType, on_delete=models.SET_NULL, null=True)
        company = models.ForeignKey('Company', on_delete=models.SET_NULL, null=True)
        job_description = models.TextField()
        salary = models.IntegerField()
        created_at = models.DateTimeField(auto_now_add=True)
    
        class Meta:
            db_table = 'job_posts'

    skill_sets table
    jobpostskillset table(intermediate table)

    • Query Parameters and Reverse Lookups
      • First we want to return the queryset of JobPostSkillSet objects that fit our search criteria
      • From that queryset, we then return the queryset of corresponding JobPost objects
        • In this particular example, let's say we send skills = ['node', 'postgresql'] as query parameters
        • These skillsets have id values of 4 and 5 respectively.
        • Notice that our JobPostSkillSet queryset returns instances 1, 5 and 6 even though instance 5 does not contain our skillset parameter.
        • This is due to the fact that JobPost instance 3 requires skills = ['mysql', 'node'] such that the JobPostSkillSet queryset will return the JobPostSkillSet instance that takes JobPost instance 3 and SkillSet instance 3 as Foreign Keys.
    class JobPostView(APIView):
    	def get(self, request):
            # we can receive all query parameter values w/ the same key values
            # and store them into a list variable
            skills = request.query_params.getlist('skills', '')
            
            # if we wish to make a query using multiple conditions from a list
            query = Q()
            for skill in skills:
                query.add(Q(skill_set__name=skill), Q.OR)
    
            job_skills = JobPostSkillSet.objects.filter(query)
            # SELECT * FROM jobpostskillset WHERE (skill_set__name='node') OR (skill_set__name='postgresql'))
    
            job_posts = JobPost.objects.filter(
                id__in=[job_skill.job_post.id for job_skill in job_skills]
            )
    
            if job_posts.exists():
                serializer = JobPostSerializer(job_posts, many=True)
                return Response(serializer.data)
    • Our final output will be serialized data of JobPost instance 1 and 3:
    [
        {
            "id": 1,
            "position_type": "permanent",
            "company": {
                "id": 1,
                "company_name": "company1"
            },
            "job_description": "jd1",
            "salary": 100000000,
            "skiilsets": [
                "postgresql"
            ]
        },
        {
            "id": 3,
            "position_type": "permanent",
            "company": {
                "id": 3,
                "company_name": "company3"
            },
            "job_description": "jd3",
            "salary": 100000000,
            "skiilsets": [
                "mysql",
                "node"
            ]
        }
    ]

     

    •  JobType and Company are both in a many-to-one relationship with JobPost.
      • When creating model instances, we must save its Foreign Key object instances in a separate manner after the request data has been validated.
    class JobPostView(APIView):
    
        def post(self, request):
            job_type = request.data.get("job_type", None)
            company_name = request.data.get("company_name", None)
            
            try: 
                job_type_instance = JobType.objects.get(job_type=job_type)
            except JobType.DoesNotExist:
                return Response({"message": "Please enter a valid job type"}, status=status.HTTP_400_BAD_REQUEST)
    
            try:
                Company.objects.get(company_name=company_name)
            except Company.DoesNotExist:
                company_instance = Company(company_name=company_name).save()
    
            job_serializer = JobPostSerializer(data=request.data)
            if job_serializer.is_valid():
                job_serializer.save(company=company_instance, job_type=job_type_instance)
                return Response(status=status.HTTP_200_OK)
    
            return Response(job_serializer.errors, status=status.HTTP_400_BAD_REQUEST)
Designed by Tistory.