Omar Jandali
Omar Jandali

Reputation: 824

Failing to lookup a field with a foreign key subfield in Django Rest Framework

I am using the django framework to serialize a django object. I have a profile model and the first field in the model is a foreignkey of the user object. I want to be able to pass a usename is the url patters for the profile. In the Views, I want to be able to take that username and go through the user foreignkey and find the profile with that username user. THis is what I have right now in my code:

Views.py

class ProfileListView(ListAPIView):
    query_set = Profile.objects.all()
    serializer_class = ProfileSerializer

class ProfileDetailView(RetrieveAPIView):
    query_set = Profile.objects.all()
    serializer_class = ProfileSerializer
    lookup_field = 'user__username'

urls.py

path('profile/', ProfileListView.as_view()),
path('profile/<username>', ProfileDetailView.as_view()),

serializers.py

class ProfileSerializer(serializers.ModelSerializer):
    class Meta:
        model = Profile
        fields = ('user', 'gender', 'phone', 'ip_address', 'dob_month', 'dob_day',
                  'dob_year', 'address_street', 'address_city', 'address_state',
                  'address_postal', 'address_country', 'profile_pic', 'role')

models.py

class Profile(models.Model):
    user = models.ForeignKey(User, on_delete=models.CASCADE)
    gender = models.CharField(max_length=12, choices=GENDER_CHOICES) # entity type
    phone = models.CharField(max_length=22)
    ip_address = models.CharField(max_length=32)
    dob_month = models.CharField(max_length=22, choices=MONTH_CHOICES)
    dob_day = models.SmallIntegerField()
    dob_year = models.SmallIntegerField()
    address_street = models.CharField(max_length=140)
    address_city = models.CharField(max_length=22)
    address_state = USStateField()
    address_postal = models.IntegerField()
    address_country = models.CharField(max_length=22)
    profile_pic = models.ImageField(upload_to='profile_pics/')
    role = models.CharField(max_length=12, choices=ROLE_CHOICES)
    created_at = models.DateTimeField(auto_now_add=True)

    def __str__(self):
        return self.user.username + ' - ' + self.type

Upvotes: 1

Views: 717

Answers (1)

ruddra
ruddra

Reputation: 52028

One way of doing is to override get_object method. Try like this:

class ProfileDetailView(RetrieveAPIView):
    queryset = Profile.objects.all()  # it should be queryset not query_set
    serializer_class = ProfileSerializer

    def get_object(self):
       return self.queryset.get(user__username=self.kwargs.get('username')).first()

There are some alternate solutions as well. For that please check this answer in SO.

Upvotes: 2

Related Questions