I have a simple admin form:
class SomeForm(forms.ModelForm):
class Meta:
model = Process
fields = ["start", "end", "result", "description", "user"]
def __init__(self, user=None, *args, **kwargs):
user = kwargs.pop("user", None)
super().__init__(*args, **kwargs)
self.fields["user"].initial = user
The form is being instanciated by a normal ModelAdmin:
class SomeAdmin(admin.ModelAdmin):
form = SomeForm
def get_form_kwargs(self, request):
return {"user": request.user}
def get_form(self, request, obj=None, change=False, **kwargs):
form = super().get_form(request, obj, change, **kwargs, **self.get_form_kwargs(request))
return form
The output of the print
statement is never visible in the terminal. Why? I want to be able to access the "user" as an initial value in the form:
Edit: Code updated according to @Willem Van Onsem's input (still not working: Error: TypeError
saying modelform_factory() got an unexpected keyword argument 'user'
.)
Django's ModelAdmin
has no get_form_kwargs
, yes I know that is strange, since it has a .get_formset_kwargs(…)
[Django-doc]. But, well, the ModelAdmin
is a bit of a misfeature, especially since it is a collection of different views, but it basically violates all patterns the Django views implement. For example it does not make an instance of the view, so self.request
is not accessible, since that is the ModelAdmin
, not the view object.
We can do this, but it is ugly, no, really. First we update the form to use self._user
as attribute:
class SomeForm(forms.ModelForm):
_user = None
class Meta:
model = Process
fields = ['start', 'end', 'result', 'description', 'user']
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.fields['user'].initial = self._user
and now we can each time subclass is and inject the user as attribute:
class SomeAdmin(admin.ModelAdmin):
def get_form(self, reqmuest, obj=None, change=False, **kwargs):
class SubSomeForm(SomeForm):
_user = request.user
return SomeSubForm
and that will be the working mechanism.