4

I'm following the Wagtail documentation to customize the user model. I want to add an image to the user model.

Django version: 2.0.8, Wagtail version: 2.1

Problem

After choosing an image with the image chooser field and clicking 'Save', this error shows up:

'No file was submitted. Check the encoding type on the form.'

Code

models.py

from django.db import models

from django.contrib.auth.models import AbstractUser

class User(AbstractUser):
    display_image = models.ForeignKey('wagtailimages.Image', 
        null=True,
        blank=True,
        on_delete=models.SET_NULL,
        related_name='+')

forms.py

from django import forms
from django.utils.translation import ugettext_lazy as _

from wagtail.users.forms import UserEditForm, UserCreationForm
from wagtail.images.widgets import AdminImageChooser

class CustomUserEditForm(UserEditForm):
    display_image = forms.ImageField(
        widget=AdminImageChooser(), label=_('Autorenbild'))

class CustomUserCreationForm(UserCreationForm):
    display_image = forms.ImageField(
        widget=AdminImageChooser(), label=_('Autorenbild'))}

edit.html

{% extends "wagtailusers/users/edit.html" %}

{% block extra_fields %}
    {% include "wagtailadmin/shared/field_as_li.html" with field=form.display_image %}
{% endblock extra_fields %}

{% block extra_js %}
    {{ block.super }}
    {% include 'wagtailadmin/pages/_editor_js.html' %}
{% endblock extra_js %}

create.html similar

What I've tried so far

The idea to use the AdminImageChooser widget I found here. I had to adjust the forms by adding an forms.ImageField so that the User page displays without error.

Questions

  1. Anyone know why the error occurs and how to fix it?

  2. As stated in the above Google group thread, it seems as adding an image to the user model is 'a bit awkward'. What is a better approach to have an image connected to an user for repetitive usage in a site? A requirement is that the image can be easily changed in Wagtail admin.

Other problem with Wagtail version 2.2

In Settings > User in the admin interface, the window of the AdminImageChooser does not open.

Console shows following JS error:

Uncaught ReferenceError: createImageChooser is not defined

Paolo
  • 20,112
  • 21
  • 72
  • 113

4 Answers4

2

On Django 3.0.7 and wagtail wagtail 2.9, I could solve it like this:

models.py

class User(AbstractUser):
avatar = models.ForeignKey(
    'wagtailimages.Image',
    null=True,
    blank=True,
    on_delete=models.SET_NULL,
    related_name='+'
)

forms.py

It's important to use an ModelChoiceField and not an ImageField, so you are compliant with the AdminImageChooser widget.

from django import forms

from wagtail.images import get_image_model
from wagtail.images.widgets import AdminImageChooser
from wagtail.users.forms import UserCreationForm, UserEditForm


class CustomUserEditForm(UserEditForm):
    avatar = forms.ModelChoiceField(
        queryset=get_image_model().objects.all(), widget=AdminImageChooser(),
    )


class CustomUserCreationForm(UserCreationForm):
    avatar = forms.ModelChoiceField(
        queryset=get_image_model().objects.all(), widget=AdminImageChooser(),
    )

Templates

No need to load any Javascript manually. The widget do it for you.

Any-templates-dir/wagtailusers/users/create.html

{% extends "wagtailusers/users/create.html" %}

{% block extra_fields %}
  {% include "wagtailadmin/shared/field_as_li.html" with field=form.avatar %}
{% endblock extra_fields %}

Any-templates-dir/wagtailusers/users/edit.html

{% extends "wagtailusers/users/edit.html" %}

{% block extra_fields %}
  {% include "wagtailadmin/shared/field_as_li.html" with field=form.avatar %}
{% endblock extra_fields %}
Tam
  • 84
  • 1
  • 6
1

Was using the last proposed solution in the same Google groups thread, also got the ReferenceError: createImageChooser is not defined js problem after updating from Wagtail 2.1 to 2.2

Here is how my research went:

Looks like this commit removed direct media js inclusion from _editor_js.html.

Okay, so the solution is to replicate the old behavour, and access the Media subclasses of widgets

First I tried adding the same removed lines to my own edit.html in {% block extra_js %}. Did not work.

Looks like some views return edit_handler, like here. User view does not.

What user view does provide, however, is form variable, in both create and edit views. Let's use it.

And the final solution for me was changing extra_js block in edit.html like so:

{% block extra_js %}
    {{ block.super }}
    {% include 'wagtailadmin/pages/_editor_js.html' %}
    {{ form.media.js }}
{% endblock extra_js %}
p5vq9k
  • 11
  • 2
0

models.py

class User(AbstractUser):
first_name = models.CharField(max_length=40, blank=False)
image = models.ImageField(blank=False, null=False, upload_to='image/', default='img/user.jpg') 



def __str__(self):
    return self.username

'''here you can add a model and their requirements too u can set path to remember one thing that image folder will create in media folder..so don't forget to add that folder there. like if you find it helpful'''

forms.py

class UserRegistrationForm(forms.ModelForm):

  confirm_password2 = forms.CharField(widget=forms.PasswordInput,required=False)     


class Meta:
 model = User
 fields = ['first_name','username','password','confirm_password2','image']

 def clean(self):
   cleaned_data = super(UserRegistrationForm, self).clean()
   password = cleaned_data.get("password")
   confirm_password2 = cleaned_data.get("confirm_password2")
   if password != confirm_password2:
    self.add_error('confirm_password2', "Password does not match")
    return cleaned_data

'''def clean for password validation and i directly added fields which field i want in it'''

views.py

def Register_view(request):
form = UserRegistrationForm()
if request.method == 'POST':
  form = UserRegistrationForm(request.POST, request.FILES)
  if form.is_valid():
        user = form.save(commit=False)
        password = form.cleaned_data.get("password")
        user.set_password(password)
        user.save()
        return redirect('login')
return render(request, 'register.html', {'form': form})

''' use request.files to add imagein your form'''

register.html

         <form action="{% url 'register' %}" method="post" enctype="multipart/form-data">
            {% csrf_token %}
            <div class="body bg-gray">
                <div class="form-group">
                    {{ form.as_p }}
                </div>
            </div>

            <div class="footer">                    

                <button type="submit" class="btn bg-olive btn-block">Sign me up</button>

                <a href="{% url 'login' %}" class="text-center">I already have Account</a>
            </div>
        </form>

''' user multipart to add image in it'''

Mohit Verma
  • 53
  • 1
  • 1
  • 10
0

For me the solution was to make sure you initialise the image field widget on the create and edit form classes with the AdminImageChooser

from wagtail.users.forms import UserEditForm
from wagtail.images.widgets import AdminImageChooser


class CustomUserEditForm(UserEditForm):
    ...
    mugshot = AdminImageChooser()

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.fields['mugshot'].widget = AdminImageChooser()

You need to do this when you subclass the UserCreationForm too.

Django 3.2.6, Wagtail 2.14

Zemogle
  • 584
  • 4
  • 16