filozof
filozof

Reputation: 91

Django admin - Hidden field - Cannot assign must be an instance

I have a CustomUser model with ForeignKey to another model. In my Signup form, I'm using a hidden field that is populated with a value depending on a search result from the user (the user is searching for a company and after clicking on the result the hidden input value represents that company's ID). When I'm saving the User object I can easily get the ID, make a query and add the company object to the field.

The problem is with my Admin. The Admin is using the same form and the company field is rendered as hidden with the ID value. When I try to change some User info and try to save it I get this error: Cannot assign "'3'": "CustomUser.kompanija" must be a "Kompanija" instance.

I thought that the Admin is using the same save method from my custom UserAccountAdapter...?

Is it possible to override the hidden input just for the Admin to show:

forms.ModelChoiceField(queryset=Kompanija.objects.all(), empty_label="Kompanija")

with initial value from the saved user object?

My models.py:

class Kompanija(models.Model):
    naziv = models.CharField(max_length=50)
    adresa = models.CharField(max_length=50, blank=True)

    def __str__(self):
        return self.naziv

class CustomUser(AbstractUser):
    ime = models.CharField(max_length=30, default='')
    prezime = models.CharField(max_length=30, default='')
    kompanija = models.ForeignKey(Kompanija, on_delete=models.CASCADE, null=True, blank=True)
    is_premium = models.BooleanField('premium status', default=False)

    def __str__(self):
        return self.email

My forms.py:

class CustomUserCreationForm(UserCreationForm):
    ime = forms.CharField(max_length=30, label='Ime')
    prezime = forms.CharField(max_length=30, label='Prezime')
    kompanija = forms.CharField(widget=forms.HiddenInput())

    class Meta(UserCreationForm):
        model = CustomUser
        fields = ('username', 'email', 'ime', 'prezime')

class CustomUserChangeForm(UserChangeForm):
    ime = forms.CharField(max_length=30, label='Ime')
    prezime = forms.CharField(max_length=30, label='Prezime')
    kompanija = forms.CharField(widget=forms.HiddenInput())

    class Meta:
        model = CustomUser
        fields = ('username', 'email', 'ime', 'prezime')


class CustomSignupForm(SignupForm):
    ime = forms.CharField(max_length=30, label='Ime')
    prezime = forms.CharField(max_length=30, label='Prezime')
    kompanija = forms.CharField(widget=forms.HiddenInput())

    class Meta:
        model = CustomUser

    def signup(self, request, user):
        user.ime = self.cleaned_data['ime']
        user.prezime = self.cleaned_data['prezime']
        user.kompanija = Kompanija.objects.get(id=self.cleaned_data['kompanija'])
        user.save()
        return user

My adapter.py:

class UserAccountAdapter(DefaultAccountAdapter):

    def save_user(self, request, user, form, commit=True):
        user = super(UserAccountAdapter, self).save_user(request, user, form, commit=False)
        user.ime = form.cleaned_data.get('ime')
        user.prezime = form.cleaned_data.get('prezime')
        user.kompanija = Kompanija.objects.get(id=form.cleaned_data.get('kompanija'))
        user.save()

My admin.py:

class CustomUserAdmin(UserAdmin):
    add_form = CustomUserCreationForm
    form = CustomUserChangeForm
    model = CustomUser
    list_display = ['email', 'ime', 'prezime', 'username', 'kompanija', 'is_premium']

    fieldsets = (
        (('Korisnik'), {'fields': ('email', 'ime', 'prezime', 'username', 'kompanija', 'is_premium')}),
    )


admin.site.register(CustomUser, CustomUserAdmin)
admin.site.register(Kompanija)

My settings.py:

ACCOUNT_FORMS = {
'signup': 'korisnici.forms.CustomSignupForm',
}

ACCOUNT_ADAPTER = 'korisnici.adapter.UserAccountAdapter'

Upvotes: 0

Views: 312

Answers (1)

filozof
filozof

Reputation: 91

After some more research and crashing my site, I found a solution to this. I needed to add ModelForm in my forms.py just for the Admin site.

In my forms.py I added:

class CustomUserAdminForm(forms.ModelForm):
  class Meta:
    model = CustomUser
    fields = ('email', 'ime', 'prezime', 'username', 'kompanija', 'is_premium')

And my admin.py:

class CustomUserAdmin(UserAdmin):
    form = CustomUserAdminForm
    model = CustomUser
    list_display = ['email', 'ime', 'prezime', 'username', 'kompanija', 'is_premium']

    fieldsets = (
        (('Korisnik'), {'fields': ('email', 'ime', 'prezime', 'username', 'kompanija', 'is_premium')}),
    )

admin.site.register(CustomUser, CustomUserAdmin)
admin.site.register(Kompanija)

Now everything works as expected.

Upvotes: 1

Related Questions