Metadata-Version: 2.4
Name: django-genfkadmin
Version: 0.3.2
Summary: No frills GenericForeignKeys for your Django Admin
Author-email: Michael Spallino <mikehspallino@gmail.com>
Maintainer-email: Michael Spallino <mikehspallino@gmail.com>
License-Expression: MIT
Project-URL: Homepage, https://github.com/mikespallino/django-genericfkadmin
Project-URL: Issues, https://github.com/mikespallino/django-genericfkadmin/issues
Project-URL: Source, https://github.com/mikespallino/django-genericfkadmin
Project-URL: Changelog, https://github.com/mikespallino/django-genericfkadmin/blob/main/CHANGELOG.md
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: Topic :: Software Development :: Libraries
Classifier: Topic :: Software Development :: Libraries :: Application Frameworks
Classifier: Framework :: Django :: 5.1
Classifier: Framework :: Django :: 5.2
Classifier: Framework :: Django :: 6.0
Classifier: Programming Language :: Python
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Programming Language :: Python :: 3.14
Classifier: Operating System :: OS Independent
Requires-Python: <3.15,>=3.10
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: django>=5.1
Dynamic: license-file

# Django GenericFKAdmin

Using `GenericForeignKey` in your Django models is cool, the default behavior
of Django Admin is not. This package allows you to replace the `content_type`
and `object_id` fields in your admin forms with a single input that is
prefilled with only the models related through `GenericRelation` fields.

## Setup

### Install

```shell
pip install django-genfkadmin
````

```shell
uv add django-genfkadmin
```

### Usage

Using this package is pretty simple.

1. Create a subclass of `GenericFKModelForm` for your model.
2. Create a subclass of `GenericFKAdmin` for your model.
3. ???
4. Profit!

e.g. in your `admin.py`

```python
from genfkadmin.admin import GenericFKAdmin


@admin.register(Pet)
class PetAdmin(GenericFKAdmin):
    pass
```

![example](docs/screenshots/example_base_admin.png)

#### Providing a `filter_callback`

If you want to further filter the queryset (perhaps by something related to
the parent instance of your model with `GenericForeignKey`) you can define a
method on your admin class as follows:

```python
@admin.register(MarketingMaterial)
class MarketingMaterialAdmin(GenericFKAdmin):

    def filter_callback(
        self,
        queryset: QuerySet,
        obj: MarketingMaterial | None = None,
    ):
        if obj:
            return queryset.filter(customer=obj.customer)
        return queryset
```

Now when loading an existing `MarketingMaterial`, the `content_object` options
are filtered by the chosen `Customer`
![example](docs/screenshots/example_filter_admin.png)

#### Using GFK Resolved Values

You might want to utilize the object of the GenericForeignKey field somewhere
in your form code, such as your clean method. To do this use the
`get_generic_field_name_for` method.

```python
class GenreAdminForm(GenericFKModelForm):

    class Meta:
        model = Genre
        fields = "__all__"

    def clean(self):
        super().clean()
        media_generic_field = self.get_generic_field_name_for("media")
        media = self.cleaned_data[media_generic_field]
        if media.name.lower() != media.name:
            raise ValidationError({media_generic_field: "media name must be lowercase"})
        return self.cleaned_data
```

A complete example django app exists in this repository at [here](/example)
