Django API: How to get all objects that match certain value - ForeignKey that is UUID

When trying to query objects on their foreignkey field, I don’t manage to get any details. The company ID is and uuid (uuid4) field.

I have a Model called “contacts”:

class Contact(models.Model):
    firstname = models.CharField(max_length=35)
    lastname = models.CharField(max_length=35)
    company = models.ForeignKey(Company, on_delete=models.CASCADE)

I want to get all Contacts, that work for the same company. Therefore I have created a ListAPIView whitin views.py
Views.py

class ContactViewSet(viewsets.ModelViewSet):
    queryset = Contact.objects.all()
    serializer_class = ContactSerializer


class CompanyContactsListView(generics.ListAPIView):
    serializer_class = ContactSerializer

    def get_queryset(self):
        company = self.kwargs['company']
        return Contact.objects.filter(company=company)

And to get a URL I added the path in urls.py

urlpatterns = [
    path('', include(router.urls)),
    path('contacts/<uuid:company>/', CompanyContactsListView.as_view(), name='contacts')
]

Problem is, that when i try to go for that path and enter an UUID of an company that exists and has related contacts, I get the following error

HTTP 404 Not Found
Allow: GET, PUT, PATCH, DELETE, HEAD, OPTIONS
Content-Type: application/json
Vary: Accept

{
    "detail": "Not found."
}

Is it possible, that my URL is wrong and therefore cant query the ListAPIView?
Because I want result like that:

[
    {
        "id": 1,
        "firstname": "Joshuah",
        "lastname": "Bankhurst",
        "company": "e871c47b-9b91-4cf9-94a6-e8135510c11d"
    },
    {
        "id": 2,
        "firstname": "Clayborn",
        "lastname": "Sylett",
        "company": "e871c47b-9b91-4cf9-94a6-e8135510c11d"
    }
]
  • I am trying to access the endpoint on contacts/e871c47b-9b91-4cf9-94a6-e8135510c11d

-This is model of company:

class Company(models.Model):
    id = models.UUIDField(primary_key=True, default=uuid.uuid4(), editable=False)
    company_name = models.CharField(max_length=55)
    location = models.CharField(max_length=55)
    about = models.TextField()

    class Meta:
        verbose_name = "Company"
        verbose_name_plural = "Companys"

    def __str__(self):
        return self.company_name

Thanks!

Have you tried updating this to:

path('contacts/<uuid:id>/', CompanyContactsListView.as_view(), name='contacts')
1 Like

A bit of a guess, but try either
return Contact.objects.filter(company_id=company)
or
return Contact.objects.filter(company__id=company)

1 Like

I tried it, but the result is still the same. What I did now after hours of googling, is that I changed the Serializer to:

class ContactSerializer(serializers.ModelSerializer):
    company = CompanySerializer(many=False)
    class Meta:
        model = Contact
        fields = '__all__'

That changed the output on the endpoint to following:

[
    {
        "id": 7,
        "company": {
            "id": "3e3111a4-76da-4e1d-9ede-ee449dc63009",
            "company_name": "Company1",
            "about": "AAA BBB CCC DDD EEE FFF GGGG!"
        },
        "firstname": "Thomas",
        "lastname": "Macl",
    }
]

Is there a way to address the ID by e. g.

return Contact.objects.filter(company.id=company_uuid)

?

Thanks for your answer, but in my case this didn’t work :confused:
I added how I changed the serializer in the other comment, maybe there is a way to directly refer to the id?

I added the code to GitHub, maybe it helps to recreate my problem: GitHub - kruppy/endpoint_test

After looking at your code, I need to ask - did you try my code exactly as I posted it, or did you make changes to it? Because what’s in your repo is not what I posted.

I also need to ask - have you verified that that UUID is actually in your database?

I also noticed:

This isn’t right - the expression uuid.uuid() is going to be evaluated once, when the model is built within Django. I’m assuming you want a different uuid be generated each time the default is required, so you want that line to be:
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)

See the docs for default.

Hi Ken, thank you for your answer. I tried several approaches that have been posted here, I didn’t manage to make it work :confused:
I also checked for type, that’s what I get when I look up the fields for company ID:

django.db.models.fields.related.ForeignKey: company

And that’s the result of looking up for contacts:

django.db.models.fields.UUIDField: id

On the get_queryset method I tried both, to use ‘company_id’ and ‘company__id’ but I still get the 404 response.
I try to access the endpoint on ‘/contacts/3e3111a4-76da-4e1d-9ede-ee449dc63009/’

Have you verified that this UUID is actually in the database?

Yes, when receiving the companys following is returned:

[
    {
        "id": "e871c47b-9b91-4cf9-94a6-e8135510c11d",
        "company_name": "Google",
        "about": "..."
    },
    {
        "id": "3e3111a4-76da-4e1d-9ede-ee449dc63009",
        "company_name": "Netflix",
        "about": "..."
    },
    {
        "id": "ed5c4620-d9c9-4699-ba54-21f0e5192448",
        "company_name": "Commerzbank",
        "about": "...
]

Therefore it should match with the id of ‘Netflix’

Ok, but do you have any Contacts that have the FK to Netflix?

I have one contact that has its ID:

[
    {
        "id": 7,
        "company": {
            "id": "3e3111a4-76da-4e1d-9ede-ee449dc63009",
            "company_name": "Netflix",
            "about": "..."
        },
        "firstname": "Thomas",
        "lastname": "Macl",
    }
]

If I use that ID then to obtain the list of contacts which are linked to ‘Netflix’, I get 404 error.

What happens if you try to run the query from the shell?

Contact.objects.filter(company_id='3e3111a4-76da-4e1d-9ede-ee449dc63009')

Then I get

<QuerySet [<Contact: Thomas Macl>]>

Try one more thing for me - take the hyphens out of the url when you submit the request.
e.g.
/contacts/3e3111a476da4e1d9edeee449dc63009/

(Sqlite stores UUIDs as an unhyphenated char 32 - it’s possible that DRF isn’t “recognizing” that this is a UUID field and is passing it through the query in its hyphenated format.)

Hi, I got a solution from another site, this was the solution for me:
Thank you very much for your patience and help!!

It looks like the query is not matching the uuid pk field in the get queryset method. Assuming that the company uuid is being passed in the kwargs, the query should match on the pk of the Company model.

CompanyContactsListView was not getting called, because the urls path /contacts/ was matching on the router, not the view class.
Lets also change the param name in the kwargs to be more explict. company_uuid

company/urls.py

router = DefaultRouter()
router.register("companys", CompanyViewSet)
router.register("benefits", BenefitsViewSet)
router.register("contacts", ContactViewSet)
router.register("jobpost", JobpostViewset)


urlpatterns = [
    path('', include(router.urls)),
    path('contact-list/<uuid:company_uuid>/', CompanyContactsListView.as_view(), name='contacts'),
]

contract_viewset.py

class CompanyContactsListView(generics.ListAPIView):
    serializer_class = ContactSerializer

    def get_queryset(self):
        company_uuid = self.kwargs['company_uuid']
        return Contact.objects.filter(company__id=company_uuid)