# Get current user in form (formset)

**URL:** https://forum.djangoproject.com/t/get-current-user-in-form-formset/43816
**Category:** The Admin
**Created:** [December 28, 2025, 11:18am UTC](https://forum.djangoproject.com/t/get-current-user-in-form-formset/43816 "2025-12-28T11:18:01Z")
**Posts on this page:** 13
**Page:** 1

<div class="post-metadata">

### Author: ![Jrol123](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.djangoproject.com/jrol123/32/31066_2.png) [@Jrol123](https://forum.djangoproject.com/u/Jrol123)
#### Post date: [December 28, 2025, 11:18am UTC](https://forum.djangoproject.com/t/get-current-user-in-form-formset/43816/1 "2025-12-28T11:18:01Z")

</div>

Hi!  
I want to fill in the first line of my inline with current user, but don’t really understand how to do so.

Current inline and formset:

```python
class AuthorInlineFormset(BaseGenericInlineFormSet):
    def __init__ (self, *args, **kwargs):
        self.request = kwargs.pop("request", None)
        super(). __init__ (*args, **kwargs)

    def save_new(self, form, commit=True):
        instance = super().save_new(form, commit=False)
        instance.department_at_moment = instance.employee.department
        if self.request and instance.employee == self.request.user:
            instance.has_read = True
        if commit:
            instance.save()
            if form.cleaned_data.get("save_m2m", True):
                form.save_m2m()
        return instance

class AuthorInline(GenericTabularInline):
    model = Author
    extra = 1
    formset = AuthorInlineFormset
    fields = ("employee", "int_affiliation", "role")
    autocomplete_fields = ["employee"]
    classes = (
        "author-inline",
        "basic_author-inline",
    )

```

The model:

```python
class Author(models.Model):
    content_type: ForeignKey = ForeignKey(
        ContentType, on_delete=models.CASCADE, null=True, blank=True
    )
    object_id: models.PositiveIntegerField = models.PositiveIntegerField()
    content_object = GenericForeignKey("content_type", "object_id")
    employee: ForeignKey = ForeignKey(
        settings.AUTH_USER_MODEL,
        on_delete=models.CASCADE,
        related_name="author",
        verbose_name="Автор",
    )
    department_at_moment: ForeignKey = ForeignKey(
        Department,
        # to_field="name",
        on_delete=models.CASCADE,
        related_name="author",
        verbose_name="Департамент",
        help_text="Департамент, в котором автор был на момент работы",
    )
    int_affiliation: Uint1Field = Uint1Field(
        default=1, verbose_name="Количество аффиляций"
    )
    role: CharField = CharField(
        max_length=20, blank=True, null=True, verbose_name="Роль"
    )
    has_read: BooleanField = BooleanField(
        default=False,
        db_comment="Прочитал ли пользователь объект, в котором его указали",
    )

```

---

<div class="post-metadata">

### Author: ![KenWhitesell](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.djangoproject.com/kenwhitesell/32/280_2.png) [@KenWhitesell](https://forum.djangoproject.com/u/KenWhitesell)
#### Post date: [December 28, 2025, 12:04pm UTC](https://forum.djangoproject.com/t/get-current-user-in-form-formset/43816/2 "2025-12-28T12:04:16Z")

</div>

Welcome @Jrol123 !

First, a side note: When posting code here, please get rid of excess blank lines. Having double or triple spaced lines makes the code extremely difficult to read here. (I’ve taken the liberty of editing your original post to condense it.)

> [@Jrol123](#):
>
> I want to fill in the first line of my inline with current user,

When you create the instance of the formset, you can set initial values - see [Formsets | Django documentation | Django](https://docs.djangoproject.com/en/6.0/topics/forms/formsets/#using-initial-data-with-a-formset). (It’s worth reviewing the entire page.)

We might be able to provide more specific assistance if you post the view in which you are rendering and using this formset.

I’m also not sure I understand why you are using a generic version of these formsets. Can you explain the situation in more detail? (This may simply become more clear once I see how you’re using this.)

---

<div class="post-metadata">

### Author: ![Jrol123](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.djangoproject.com/jrol123/32/31066_2.png) [@Jrol123](https://forum.djangoproject.com/u/Jrol123)
#### Post date: [December 28, 2025, 12:29pm UTC](https://forum.djangoproject.com/t/get-current-user-in-form-formset/43816/3 "2025-12-28T12:29:03Z")

</div>

Okay!  
Will check a bit later. Will reply again after i review the link you sent me.

In a mean time, if i recall correctly, i use generic versions because of the generic foreign key of the Author model, but i may be wrong, because i was doing this part when i just started my project and was relying heavily on the Deepseek to guide me at my first steps.

P. S.  
Thanks for formatting my code. It looks much better now, and sorry that i didn’t format it myself as i posted it.

P. P. S. Before i leave to check the link, could you explain, please, why does the `AuthorInlineFormset.save_existing()` doesn’t trigger when i try and change some data in the model, that uses it as inline?  
I don’t change nothing on the Inline itself, just some fields on the ‘parent’ model

```python
def save_existing(self, form, instance, commit=True):
        if self.request and instance.employee == self.request.user:
            instance.has_read = True
        if 'employee' in form.changed_data:
            instance.department_at_moment = instance.employee.department
        return super().save_existing(form, instance, commit)

```

---

<div class="post-metadata">

### Author: ![KenWhitesell](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.djangoproject.com/kenwhitesell/32/280_2.png) [@KenWhitesell](https://forum.djangoproject.com/u/KenWhitesell)
#### Post date: [December 28, 2025, 12:45pm UTC](https://forum.djangoproject.com/t/get-current-user-in-form-formset/43816/4 "2025-12-28T12:45:30Z")

</div>

The snippets you’re showing here aren’t enough to answer your questions.

We would need to see the complete view that is using this formset, and if there are other questions concerning the formset, the complete code for that as well.

I don’t see a documented `save_existing` api on a form or a formset - I wouldn’t suggest trying to use it.

---

<div class="post-metadata">

### Author: ![Jrol123](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.djangoproject.com/jrol123/32/31066_2.png) [@Jrol123](https://forum.djangoproject.com/u/Jrol123)
#### Post date: [December 29, 2025, 12:02pm UTC](https://forum.djangoproject.com/t/get-current-user-in-form-formset/43816/5 "2025-12-29T12:02:46Z")

</div>

So, i was able to look at the link you send and yeah, that’s almost exactly the thing i was looking for!  
The only problem is that it always creates a new form when i open an already created object with its inline.

Any suggestions how to fix it?

```python
class AuthorInlineFormset(BaseGenericInlineFormSet):
    def __init__ (self, *args, **kwargs):
        self.request = kwargs.pop("request", None)
        super(). __init__ (initial=[{"employee": self.request.user}], *args, **kwargs)

    def save_new(self, form, commit=True):
        instance = super().save_new(form, commit=False)
        instance.department_at_moment = instance.employee.department
        if self.request and instance.employee == self.request.user:
            instance.has_read = True
        if commit:
            instance.save()
            if form.cleaned_data.get("save_m2m", True):
                form.save_m2m()
        return instance

```

P. S.  
It all happens in the admin panel.

P. P. S.  
I got the `save_new` and `save_existing` ideas from `BaseModelFormSet`.  
Although, in its child model, `BaseGenericInlineFormSet` there’s only `save_new`.  
Any ideas how to work with saving the existing ones?

P. P. P. S.  
I realize now that it’s because i keep the ‘extra’ field not equal to zero.  
So, now the question is:  
How to nullify the ‘extra’ field if the objects are already created?

---

<div class="post-metadata">

### Author: ![Jrol123](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.djangoproject.com/jrol123/32/31066_2.png) [@Jrol123](https://forum.djangoproject.com/u/Jrol123)
#### Post date: [December 29, 2025, 12:33pm UTC](https://forum.djangoproject.com/t/get-current-user-in-form-formset/43816/6 "2025-12-29T12:33:16Z")

</div>

Well… At the end i created this abomination:

```python
class AuthorInlineFormset(BaseGenericInlineFormSet):
    def __init__ (self, *args, **kwargs):
        self.request = kwargs.pop("request", None)
        self.parent_instance = kwargs.get("instance", None)
        if self.parent_instance and self.parent_instance.pk:
                self.extra = 0
        else:
            self.extra = 1
            if self.request and self.request.user.is_authenticated:
                kwargs["initial"] = [{"employee": self.request.user}]
        super(). __init__ (*args, **kwargs)

    def save_new(self, form, commit=True):
        instance = super().save_new(form, commit=False)
        instance.department_at_moment = instance.employee.department
        if self.request and instance.employee == self.request.user:
            instance.has_read = True
        if commit:
            instance.save()
            if form.cleaned_data.get("save_m2m", True):
                form.save_m2m()
        return instance

```

With the Inline being:

```python
class AuthorInline(GenericTabularInline):
    model = Author
    extra = 1

    formset = AuthorInlineFormset

    fields = ("employee", "int_affiliation", "role")
    autocomplete_fields = ["employee"]
    
    def get_formset(self, request, obj=None, **kwargs):
        FormSet = super().get_formset(request, obj, **kwargs)

        class RequestFormSet(FormSet):
            def __init__ (self, *args, **kwargs):
                kwargs["request"] = request
                super(). __init__ (*args, **kwargs)

        return RequestFormSet

    classes = (
        "author-inline",
        "basic_author-inline",
    )

```

I am not sure that i have done everything correctly (the step with the `get_formset` in `AuthorInline` for the request is still pretty wild for me, but it works!)

As soon as mr. [KenWhitesell](https://forum.djangoproject.com/u/kenwhitesell) checks it (because i really want to understand if i have done everything correctly) i’ll close the topic

---

<div class="post-metadata">

### Author: ![KenWhitesell](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.djangoproject.com/kenwhitesell/32/280_2.png) [@KenWhitesell](https://forum.djangoproject.com/u/KenWhitesell)
#### Post date: [December 30, 2025, 12:51pm UTC](https://forum.djangoproject.com/t/get-current-user-in-form-formset/43816/7 "2025-12-30T12:51:50Z")

</div>

> [@Jrol123](#):
>
> (because i really want to understand if i have done everything correctly)

In general, I can say that you haven’t, because you’re still using an undocumented (internal) API. (It’s undocumented for a reason, and you have no guarantees that the method will not be changed, renamed, or otherwise altered at any point in time.)

But I can’t comment on more than that without seeing the complete code for the ModelAdmin class using these, and verification that these are the complete inline and formset classes.

---

<div class="post-metadata">

### Author: ![Jrol123](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.djangoproject.com/jrol123/32/31066_2.png) [@Jrol123](https://forum.djangoproject.com/u/Jrol123)
#### Post date: [December 31, 2025, 2:23am UTC](https://forum.djangoproject.com/t/get-current-user-in-form-formset/43816/8 "2025-12-31T02:23:21Z")

</div>

> [@KenWhitesell](#):
>
> complete code for the ModelAdmin class using these

These AuthorInline are used in a bunch of different ModelAdmin’s, so i’ll show just one:

```python
@admin.register(Publication)
class PublicationAdmin(admin.ModelAdmin):
    list_display = ("id", "publication_type", "display_authors", "total_affiliation")
    autocomplete_fields = ["grant"]
    change_form_template = "admin/publications/publication/change_form.html"
    inlines = [
        AuthorWithoutRoleInline,
        AuthorOnlyInline,
        AuthorInline,
        ArticleInline,
        MonographInline,
        FieldResearchReportInline,
        CollectionInline,
    ]

    def get_fieldsets(self, request, obj=None):
        """Разделяем поля на две группы: до и после инлайна автора"""
        fieldsets = (
            (
                "Основная информация",
                {
                    "fields": (
                        "publication_type",
                        "grant",
                    ),
                },
            ),
            (
                "Дополнительная информация",
                {
                    "fields": (
                        "year_publication",
                        "quarter_publication",
                        "foreign_work",
                    ),
                },
            ),
        )
        return fieldsets

    def display_authors(self, obj):
        """
        Возвращает строку со всеми авторами, привязанными к этой публикации.
        """
        authors = Author.objects.filter(
            content_type__model="publication", object_id=obj.id
        )
        author_names = [str(author.employee) for author in authors]
        return ", ".join(author_names) if author_names else "Нет авторов"
    display_authors.short_description = "Авторы"

    def save_related(self, request, form, formsets, change):
        """
        Вызывается после сохранения всех инлайнов (авторов).
        """
        super().save_related(request, form, formsets, change)
        form.instance.total_affiliation = form.instance.calculate_total_affiliation()
        form.instance.save(update_fields=["total_affiliation"])

    def get_formsets_with_inlines(self, request, obj=None):
        formsets_with_inlines = super().get_formsets_with_inlines(request, obj)
        if obj:
            filtered_formsets = []
            for formset, inline in formsets_with_inlines:
                if (
                    (
                        isinstance(inline, AuthorWithoutRoleInline)
                        and obj.publication_type in ("collection", "article")
                    )
                    or (
                        isinstance(inline, AuthorInline)
                        and obj.publication_type == "monograph"
                    )
                    or (
                        isinstance(inline, AuthorOnlyInline)
                        and obj.publication_type == "field_research_report"
                    )
                ):
                    filtered_formsets.append((formset, inline))
                if (
                    (
                        isinstance(inline, ArticleInline)
                        and obj.publication_type == "article"
                    )
                    or (
                        isinstance(inline, MonographInline)
                        and obj.publication_type == "monograph"
                    )
                    or (
                        isinstance(inline, FieldResearchReportInline)
                        and obj.publication_type == "field_research_report"
                    )
                    or (
                        isinstance(inline, CollectionInline)
                        and obj.publication_type == "collection"
                    )
                ):
                    filtered_formsets.append((formset, inline))
            return filtered_formsets
        return formsets_with_inlines

    class Media:
        js = (
            "admin/js/jquery.init.js",
            "js/publication_admin.js",
        )
    fields = (
        "publication_type",
        "grant",
        "year_publication",
        "quarter_publication",
        "foreign_work",
    )
    readonly_fields = (
        "total_affiliation",
    )

```

And yes, the InlineFormset is used in all of the Author\*Inline types (they’re different from each other just by the fields, so i don’t see the reason to show all of them, with the exception of AuthorOnlyInline, that additionaly uses that:

```python
def formfield_for_foreignkey(
        self, db_field: ForeignKey, request: HttpRequest, **kwargs: Any
    ) -> ModelChoiceField | None:
        if db_field.name == "employee":
            kwargs["label"] = "составитель"
        return super().formfield_for_foreignkey(db_field, request, **kwargs)

```

)

If there’s a more correct way to do so, please tell me!

---

<div class="post-metadata">

### Author: ![KenWhitesell](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.djangoproject.com/kenwhitesell/32/280_2.png) [@KenWhitesell](https://forum.djangoproject.com/u/KenWhitesell)
#### Post date: [December 31, 2025, 2:01pm UTC](https://forum.djangoproject.com/t/get-current-user-in-form-formset/43816/9 "2025-12-31T14:01:18Z")

</div>

I think this helps me a lot.

To echo this back to try and confirm my understanding:

- You have a number of different models all sharing `AuthorInline` - among others.
- The `Author` model has a Generic FK to relate it to one of the model types.
  - This implies that if an `Author` has multiple `Publication`, there will be multiple instances of `Author`.
  - Given that `Author` has FKs to both “content” and `employee`, `Author` is _effectively_ the join table between `employee` and “content”. (Using the term “content” as a generic term of reference to the `Publication` types.)

Assuming the above is all correct, your original question was:

> [@Jrol123](#):
>
> I want to fill in the first line of my inline with current user, …

You have:

> [@Jrol123](#):
>
> ```auto
> class AuthorInlineFormset(BaseGenericInlineFormSet):
> def __init__ (self, *args, **kwargs):
> self.request = kwargs.pop("request", None)
> self.parent_instance = kwargs.get("instance", None)
> if self.parent_instance and self.parent_instance.pk:
> self.extra = 0
> else:
> self.extra = 1
> if self.request and self.request.user.is_authenticated:
> kwargs["initial"] = [{"employee": self.request.user}]
> super(). __init__ (*args, **kwargs)
> 
> ```

Which does appear to me to satisfy the requirement - and looks fine to me. I don’t see anything “wrong” here.

So my only question concerns the use of `save_new`. As an undocumented API, using it comes with risks regarding future updates to Django. (An undocumented function can be changed in any release without going through the deprecation process.)

Fundamentally, `save_new` ends up calling `save` on the form - which _is_ a documented API, I’d be looking at adding this functionality _there_ rather than _here_.

But I’m also quite pragmatic about such things. The last time this was changed was 7 years ago, and most of it has been stable for more than 10 years - making the likelihood of significant changes quite small.

In the end, it is your decision to make. It’s not a question of “right” vs “wrong” (or “correct” vs “incorrect”), it’s “What are you comfortable with?” It’s a tradeoff. This is probably more straight-forward than the alternatives, but does come with a risk. If you’re comfortable with that, it wouldn’t be my place to recommend against it.

---

<div class="post-metadata">

### Author: ![Jrol123](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.djangoproject.com/jrol123/32/31066_2.png) [@Jrol123](https://forum.djangoproject.com/u/Jrol123)
#### Post date: [January 2, 2026, 12:47am UTC](https://forum.djangoproject.com/t/get-current-user-in-form-formset/43816/10 "2026-01-02T00:47:54Z")

</div>

> [@KenWhitesell](#):
>
> - You have a number of different models all sharing `AuthorInline` - among others.
> - The `Author` model has a Generic FK to relate it to one of the model types.
> - This implies that if an `Author` has multiple `Publication`, there will be multiple instances of `Author`.
> - Given that `Author` has FKs to both “content” and `employee`, `Author` is _effectively_ the join table between `employee` and “content”. (Using the term “content” as a generic term of reference to the `Publication` types.)

Yeah, you’re correct!  
The `Author` is a join table, as one `employee` may take multiple `roles` on the single `Publication` and i need to save the `current_department` that the `employee` was at at the moment of creating the `Publication`.

> [@KenWhitesell](#):
>
> Fundamentally, `save_new` ends up calling `save` on the form - which _is_ a documented API, I’d be looking at adding this functionality _there_ rather than _here_.

Okay, so, the `save` is being called each time the object is being saved (both when it’s a new one and when it already exists).

I’ve done a bit of googling and came out with this:

```python
class AuthorInlineFormset(BaseGenericInlineFormSet):
    def __init__ (self, *args, **kwargs):
        self.request = kwargs.pop("request", None)
        self.parent_instance = kwargs.get("instance", None)
        if self.parent_instance and self.parent_instance.pk:
            self.extra = 0
        else:
            self.extra = 1
            if self.request and self.request.user.is_authenticated:
                kwargs["initial"] = [{"employee": self.request.user}]
        super(). __init__ (*args, **kwargs)
        
    def save(self, commit=True):
        result = super(AuthorInlineFormset, self).save(commit=False)
        for form in self.forms:
            author = form.save(commit=False)
            if author.employee == self.request.user:
                author.has_read = True
            if commit:
                author.save()
                if form.cleaned_data.get("save_m2m", True):
                    form.save_m2m()
        return result

```

So, i replaced the undocumented `save_new` with the normal `save`  
I didn’t exactly found in the documentation the part for the overriding the default save, but, as i understand correctly, it first saves but not commits the forms which i then manually commit, correct?

And now i get this error if i try to save the model with the current ‘filled in’ `Author`:

```auto
Django Version: 5.2.7
Python Version: 3.11.14
Installed Applications:
['polymorphic',
 'users',
 'django.contrib.admin',
 'django.contrib.auth',
 'django.contrib.contenttypes',
 'django.contrib.sessions',
 'django.contrib.messages',
 'django.contrib.staticfiles',
 'core',
 'publications',
 'conferences_presentations',
 'reviews',
 'organizational_work',
 'scientific_guidance',
 'teaching_activities',
 'field_study',
 'expertise',
 'admin_autoregister',
 'django_jsonform']
Installed Middleware:
['django.middleware.security.SecurityMiddleware',
 'django.contrib.sessions.middleware.SessionMiddleware',
 'django.middleware.common.CommonMiddleware',
 'django.middleware.csrf.CsrfViewMiddleware',
 'django.contrib.auth.middleware.AuthenticationMiddleware',
 'django.contrib.messages.middleware.MessageMiddleware',
 'django.middleware.clickjacking.XFrameOptionsMiddleware']

Traceback (most recent call last):
  File "/usr/local/lib/python3.11/site-packages/django/core/handlers/exception.py", line 55, in inner
    response = get_response(request)
               ^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/django/core/handlers/base.py", line 197, in _get_response
    response = wrapped_callback(request, *callback_args, **callback_kwargs)
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/django/contrib/admin/options.py", line 719, in wrapper
    return self.admin_site.admin_view(view)(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/django/utils/decorators.py", line 192, in _view_wrapper
    result = _process_exception(request, e)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/django/utils/decorators.py", line 190, in _view_wrapper
    response = view_func(request, *args, **kwargs)
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/django/views/decorators/cache.py", line 80, in _view_wrapper
    response = view_func(request, *args, **kwargs)
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/django/contrib/admin/sites.py", line 246, in inner
    return view(request, *args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/django/contrib/admin/options.py", line 1984, in add_view
    return self.changeform_view(request, None, form_url, extra_context)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/django/utils/decorators.py", line 48, in _wrapper
    return bound_method(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/django/utils/decorators.py", line 192, in _view_wrapper
    result = _process_exception(request, e)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/django/utils/decorators.py", line 190, in _view_wrapper
    response = view_func(request, *args, **kwargs)
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/django/contrib/admin/options.py", line 1843, in changeform_view
    return self._changeform_view(request, object_id, form_url, extra_context)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/django/contrib/admin/options.py", line 1895, in _changeform_view
    self.save_related(request, form, formsets, not add)
    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/django/contrib/admin/options.py", line 1342, in save_related
    self.save_formset(request, form, formset, change=change)
    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/django/contrib/admin/options.py", line 1330, in save_formset
    formset.save()
    ^^^^^^^^^^^^^^
  File "/app/src/core/authorAdmin.py", line 43, in save
    author.department_at_moment = author.employee.department
                                  ^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/django/db/models/fields/related_descriptors.py", line 271, in __get__
    raise self.RelatedObjectDoesNotExist(
    ^

Exception Type: RelatedObjectDoesNotExist at /admin/scientific_guidance/scientificguidance/add/
Exception Value: Author has no employee.

```

But when i select the other `Author` in form, everything works perfectly.  
Help, please!

P. S. Happy new year!

---

<div class="post-metadata">

### Author: ![Jrol123](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.djangoproject.com/jrol123/32/31066_2.png) [@Jrol123](https://forum.djangoproject.com/u/Jrol123)
#### Post date: [January 4, 2026, 6:16am UTC](https://forum.djangoproject.com/t/get-current-user-in-form-formset/43816/12 "2026-01-04T06:16:36Z")

</div>

The problem is that the `super().save()` returns an empty array, but if i use additional form, with the total count of 2, the `super().save()` returns an array with the length of 1.

… And now that i started testing it more thoroughly, it doesn’t even save with the `save_new` method. Not throwing any errors, but it just not creating new `Author` object.

And yeah, i really don’t understand why it doesn’t save properly. The only clue i have is the next quote from the documentation:

> If you use an initial for displaying a formset, you should pass the same initial when processing that formset’s submission so that the formset can detect which forms were changed by the user. For example, you might have something like: ArticleFormSet(request.POST, initial=[…]).

But i don’t get it. Please, help

P. S. I rewrote a `save` method a bit, both as a workaround and just to straighten things up:

```python
    @property
    def _new_init(self):
        """Is it the first time the formset being initialised"""
        return self.extra == 1

    def save(self, commit=True):
        result = super().save(commit=False)
        print(len(self.forms), len(result))
        if (self._new_init
            and not any(instance.employee == self.request.user for instance in result)
            and len(self.forms) != len(result)
        ):
            result.insert(0, self.model(content_object=self.instance, employee=self.request.user))
        for author in result:
            author.department_at_moment = author.employee.department
            if author.employee == self.request.user:
                author.has_read = True
            if commit:
                author.save()
        return result

```

---

<div class="post-metadata">

### Author: ![KenWhitesell](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.djangoproject.com/kenwhitesell/32/280_2.png) [@KenWhitesell](https://forum.djangoproject.com/u/KenWhitesell)
#### Post date: [January 4, 2026, 2:04pm UTC](https://forum.djangoproject.com/t/get-current-user-in-form-formset/43816/13 "2026-01-04T14:04:13Z")

</div>

Quite honestly, you’re digging into areas that either I’m not familiar with or have never dealt with. (e.g. GFKs in the admin, conditional initialization of inline formsets in the admin)

In the general case, this isn’t the type of view that I would be looking to implement in the admin.

My personal opinion (with no technical basis that I can directly reference), I’m getting the feeling that this is one of those cases where the effort involved in making the admin do what you want ends up involving a lot more work than if you just created the custom views yourself.

If I were doing this in a view, I’d know that I’d have complete control over the form and formset, after the data was POSTed and the formset regenerated. I could then alter that form data before calling save. But adding the admin into the mix feels like it removes one level of control from me.

I _am_ curious enough to keep looking at this myself to see if there’s something I’m missing - but I can’t say when I might find something.

Maybe one of the other members here have some thoughts or ideas to add?

---

<div class="post-metadata">

### Author: ![Jrol123](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.djangoproject.com/jrol123/32/31066_2.png) [@Jrol123](https://forum.djangoproject.com/u/Jrol123)
#### Post date: [January 5, 2026, 10:44am UTC](https://forum.djangoproject.com/t/get-current-user-in-form-formset/43816/14 "2026-01-05T10:44:20Z")

</div>

> [@KenWhitesell](#):
>
> My personal opinion (with no technical basis that I can directly reference), I’m getting the feeling that this is one of those cases where the effort involved in making the admin do what you want ends up involving a lot more work than if you just created the custom views yourself.

To be honest, maybe you’re right.  
But my project is for the internal usage and i thought to only use the admin panel. Well, it seems that i would need to learn now how the views work if i wish to rewrite the `save` method…  
Maybe even override the default admin site, but that’s the other question.

For now, i managed to make it work by making the `self.initial_authors` in the formset and then, at the `save` check if it’s an initial opening of the form (with the creation of objects, thus using the `extra` and `initial`), then manually creating and adding all the missed authors to the `result` variable and then just checking and cleaning the data.  
Hope it’ll help someone someday, but for now i’ll close this question as the solution, though not the most direct, has been found.  
Will select current message as a solution only because of the code.  
Big thanks to the @KenWhitesell for help!

```python
class AuthorInlineFormset(BaseGenericInlineFormSet):
    def __init__ (self, *args, **kwargs):
        self.request = kwargs.pop("request", None)
        self.parent_instance = kwargs.get("instance", None)
        if self.parent_instance and self.parent_instance.pk:
            self.extra = 0
            self.initial_authors = []
        else:
            self.extra = 1
            self.initial_authors = [
                {
                    "employee": self.request.user,
                    # "content_object": self.parent_instance, # Doesn't help
                }
            ]
        super(). __init__ (*args, initial=self.initial_authors, **kwargs)

    @property
    def _new_init(self):
        """If formset is initialised for the first time"""
        return self.extra == 1

    # Not the most straightforward approach, but it works. Maybe can be fixed with this. https://docs.djangoproject.com/en/5.2/topics/forms/formsets/#using-initial-data-with-a-formset
    def save(self, commit=True):
        result = super().save(commit=False)
        if self._new_init and len(self.forms) != len(result):
            # [::-1] is used for saving in the same order as authors were displayed in the form (it inflicts the order of authors after the save)
            for initial_author in self.initial_authors[::-1]:
                if not any(
                    instance.employee == initial_author["employee"]
                    for instance in result
                ):
                    result.insert(
                        0,
                        self.model(
                            content_object=self.instance,
                            employee=initial_author["employee"],
                        ),
                    )

        for author in result:
            author.department_at_moment = author.employee.department
            if author.employee == self.request.user:
                author.has_read = True
            if commit:
                author.save()
        return result

class AuthorInline(GenericTabularInline):
    model = Author
    extra = 1
    formset = AuthorInlineFormset
    fields = ("employee", "int_affiliation", "role")
    autocomplete_fields = ["employee"]

    def get_formset(self, request, obj=None, **kwargs):
        FormSet = super().get_formset(request, obj, **kwargs)
        class RequestFormSet(FormSet):
            def __init__ (self, *args, **kwargs):
                kwargs["request"] = request
                super(). __init__ (*args, **kwargs)

        return RequestFormSet

```
