# Add native support for CompositePrimaryKey in SingleObjectMixin

**URL:** https://forum.djangoproject.com/t/add-native-support-for-compositeprimarykey-in-singleobjectmixin/38715
**Category:** Django Internals
**Created:** [February 10, 2025, 6:58am UTC](https://forum.djangoproject.com/t/add-native-support-for-compositeprimarykey-in-singleobjectmixin/38715 "2025-02-10T06:58:26Z")
**Posts on this page:** 5
**Page:** 1

<div class="post-metadata">

### Author: ![cliff688](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.djangoproject.com/cliff688/32/22816_2.png) [@cliff688](https://forum.djangoproject.com/u/cliff688)
#### Post date: [February 10, 2025, 6:58am UTC](https://forum.djangoproject.com/t/add-native-support-for-compositeprimarykey-in-singleobjectmixin/38715/1 "2025-02-10T06:58:26Z")

</div>

Howdy!

Now that we have `CompositePrimaryKey` (thank you 😃 !) I wanted to make a proposal to add native support in `SingleObjectMixin`. Currently you can use generic views with CPK models by overriding `get_object` to allow filtering by the two or more path kwargs from the url which correspond to the CPK (assuming you don’t need request information).

If you have many models with `CompositePrimaryKey`s this can be a lot of boilerplate.

The proposed solution is a general mechanism using a new attribute `queryset_filter_kwargs`, which would be a mapping of `path_kwarg` and `field_name`.

```python
# models.py
class Story(models.Model):
    slug = models.SlugField(primary_key=True)
    name = models.CharField()

class Chapter(models.Model):
    pk = models.CompositePrimaryKey("story_id", "number")
    story = models.ForeignKey(
        "Story", on_delete=models.CASCADE, related_name="chapters"
    )
    number = models.PositiveIntegerField()
    title = models.CharField()
    body = models.TextField(blank=True)

```

```py
# views.py
class ChapterDetailView(DetailView):
    model = Chapter
    queryset_filter_kwargs = {
        "story_slug": "story_id", "chapter_number": "number",
    }

```

```py
# urls.py
urlpatterns = [
    path(
        "<slug:story_slug>/chapter/<int:chapter_number>/", ChapterDetailView.as_view(),
    ),
]

```

## Why `queryset_filter_kwargs`?

This is designed as a general attribute rather than something CPK-specific. While brainstorming possible solutions, I realized the problem was fundamentally about enabling queryset filtering based on multiple `url_kwargs`/fields—something I’ve needed to handle frequently.

Also, I couldn’t come up with a good cpk-specific name 😅 (considered allowing `pk_url_kwarg` to be a tuple, but also rejected).

By adopting this approach, we can eliminate the need for redundant `get_queryset()` and `get_object()` overrides, limiting such overrides to cases involving more complex queries or request-specific logic.

In addition, it could potentially also carry the work of `(pk|slug)_url_kwarg` and `(pk|slug)_field`, which seem slated for some change/removal? ([#22724 (Improve SingleObjectMixin) – Django](https://code.djangoproject.com/ticket/22724), [#21898 (SingleObjectMixin should not require slug or pk if queryset is given) – Django](https://code.djangoproject.com/ticket/21898)).

Internally, the implementation could look something like:

```auto
# in get_queryset or get_object
cpk = {
    field_name: self.kwargs.get(path_kwarg)
    for path_kwarg, field_name in self.queryset_filter_kwargs.items()
}
queryset = queryset.filter(**cpk)

```

Would love your thoughts, feedback, or ideas for improvement. Does this sound like a valuable addition to Django?

---

<div class="post-metadata">

### Author: ![cliff688](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.djangoproject.com/cliff688/32/22816_2.png) [@cliff688](https://forum.djangoproject.com/u/cliff688)
#### Post date: [February 11, 2025, 11:49am UTC](https://forum.djangoproject.com/t/add-native-support-for-compositeprimarykey-in-singleobjectmixin/38715/2 "2025-02-11T11:49:21Z")

</div>

```py
class ChapterDetailView(DetailView):
    model = Chapter
    composite_pk_url_kwargs = ("story_slug", "chapter_number")

```

I think this looks good as a composite pk-specific addition.

(PS Pardon the noise if this is a bad proposal.)

---

<div class="post-metadata">

### Author: ![csirmazbendeguz](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.djangoproject.com/csirmazbendeguz/32/19797_2.png) [@csirmazbendeguz](https://forum.djangoproject.com/u/csirmazbendeguz)
#### Post date: [February 11, 2025, 4:36pm UTC](https://forum.djangoproject.com/t/add-native-support-for-compositeprimarykey-in-singleobjectmixin/38715/3 "2025-02-11T16:36:16Z")

</div>

ah yes, SingleObjectMixin has been overlooked…

no need to add a new attribute IMO, this is related to [#35953 (Add composite PK admin support) – Django](https://code.djangoproject.com/ticket/35953), the same idea could be implemented in `SingleObjectMixin.get_object`

---

<div class="post-metadata">

### Author: ![cliff688](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.djangoproject.com/cliff688/32/22816_2.png) [@cliff688](https://forum.djangoproject.com/u/cliff688)
#### Post date: [February 13, 2025, 4:38pm UTC](https://forum.djangoproject.com/t/add-native-support-for-compositeprimarykey-in-singleobjectmixin/38715/4 "2025-02-13T16:38:08Z")

</div>

That’s OK, then. Thanks for the feedback.

I suppose I can always write my own mixins to prefer `/field1/field2/` over `/field1,field2/`.

---

<div class="post-metadata">

### Author: ![cliff688](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.djangoproject.com/cliff688/32/22816_2.png) [@cliff688](https://forum.djangoproject.com/u/cliff688)
#### Post date: [February 13, 2025, 4:50pm UTC](https://forum.djangoproject.com/t/add-native-support-for-compositeprimarykey-in-singleobjectmixin/38715/5 "2025-02-13T16:50:08Z")

</div>

> ah yes, SingleObjectMixin has been overlooked…

Opened a ticket: [#36187 (Add support for CompositePrimaryKey in SingleObjectMixin) – Django](https://code.djangoproject.com/ticket/36187)
