Home > Blockchain >  Django Django Rest Framework: get correct related objects on intermediate model
Django Django Rest Framework: get correct related objects on intermediate model

Time:06-07

I have an intermediate model with the following fields:

class UserSkill(models.Model):
    user = models.ForeignKey(User, on_delete=models.CASCADE)
    skill = models.ForeignKey(Skill, on_delete=models.CASCADE, related_name='user_skills')
    disabled = models.BooleanField(default=False)

As you can see, it has two foreign keys, one to the auth user and one to another table called skill.

I am trying to get all Skills assigned to an specific user, so I do the following get_queryset in my ViewSet:

class AssignedSkillViewSet(viewsets.ModelViewSet):
    queryset = Skill.objects.all()
    serializer_class = AssignedSkillSerializer
    permission_classes = [permissions.IsAuthenticated]

    def get_queryset(self):
        user = self.request.user
        return Skill.objects.filter(user_skills__user=user, user_skills_user__disabled=False))

Now, I also need to include the intermediate model information in the API, which I can access trough users_skills related name in DRF's Serializer, as follows:

class AssignedSkillSerializer(serializers.HyperlinkedModelSerializer):
    class Meta:
        model = Skill
        fields = [
            'id',
            'url',
            'title',
            'description',
            'user_skills',
        ]

But when I try to get that information it returns ALL user_skills related to the assigned skill, no matter if they are assigned to other users. I need the related model information only for that user and that skill.

For Example: If I have a skill named Math, and a user named Maria

related_skills = Skill.objects.filter(user_skills__user=user, user_skills_user__disabled=False)).user_skills.all()

The above code will return:

[
  <UserSkill: Math Jenniffer>,
  <UserSkill: Math Gabriel>,
  <UserSkill: Math John>,
  <UserSkill: Math Maria>,
]

I only need to get the item <UserSkill: Math Maria>. The list is not ordered in any way so getting the last item on the list does not work in all cases.

I know there is something I'm probably missing. I appreciate any help or clues you people can give me.

CodePudding user response:

I think that when you do the filter:

Skill.objects.filter(
user_skills__user=user,   #condition_1
user_skills_user__disabled=False, #condition_2
).user_skills.all()

You already did a query related to the UserSkill model. Because the filter is done in the Skill model and the #condition_1 (user_skills__user=user) uses the information from the UserSkill model to filter by users. But when you do .user_skills.all() at the end of the query you are overring the filter with all the data from the UserSkill model.

To get a list of UserSkill instances from the filter you could try:

UserSkill.objects.filter(
user="Maria", 
skill="Math",
)

CodePudding user response:

Maybe this will help
serializers.py

class SkillSerializer(serializers.ModelSerializer):
    class Meta:
        model = Skill
        fields = ['id', ...]

class UserSkillSerializer(serializers.ModelSerializer):
    skill_detail = SkillSerializer(many=True)
    class Meta:
        model = UserSkill
        fields = ['id', 'user', 'skill_detail']

views.py

class AssignedSkillViewSet(viewsets.ModelViewSet):
    queryset = UserSkill.objects.all()
    serializer_class = UserSkillSerializer
    permission_classes = [permissions.IsAuthenticated]

    def get_queryset(self):
        user = self.request.user
        return UserSkill.objects.filter(user=user, disabled=False))
  • Related