Django form.save() does not update database

Question:

I have a Django User model with a background and a profile picture, what I want to do is give the user the ability to submit a new background photo/picture and have it saved to the database. The way I have done this is like this

settings.html:

{% extends 'main.html' %}

{% block content %}
    <form action="" method="POST">    
        {% csrf_token %}
        {{ form.as_p }}
        <input type="submit" name="user-settings-save" value="submit">
    </form>
{% endblock content %}

forms.py

class UserProfileForm(ModelForm):
    class Meta:
        model = User
        fields = ['avatar', 'background']

models.py

class User(AbstractBaseUser, PermissionsMixin):
    email = models.EmailField(blank=True, default='', unique=True)
    password = models.CharField(max_length=50)
    name = models.CharField(max_length=255, default='', unique=True)

    avatar = models.ImageField(default='default.png', upload_to ='uploads/')
    background = models.ImageField(default='default.png', upload_to ='uploads/')

    score = models.IntegerField(default=1)

    is_staff = models.BooleanField(default=False)
    is_superuser = models.BooleanField(default=False)

    is_active = models.BooleanField(default=True)
    is_verified = models.BooleanField(default=False)

    register = models.CharField(max_length=255, default='')

    objects = CustomUserManager()

    USERNAME_FIELD = 'email'
    EMAIL_FIELD = 'email'
    REQUIRED_FIELDS = ['name']

    def __str__(self):
        return self.name

views.py

def userSettings(request):
    form = UserProfileForm(instance=request.user)

    if request.method == 'POST': 
        if 'user-settings-save' in request.POST:
            form = UserProfileForm(request.POST, request.FILES, instance=request.user)
            if form.is_valid():
                if backendActionAuth(request, 'user-settings-save', form):
                    form.save()
                    return redirect('user-profile', request.user.id)



    context = {'form': form}

    return render(request, 'base/settings.html', context)

and urls.py

urlpatterns = [
    path('', views.home, name="home"),
    path('post/<str:pk>/', views.post, name="post"),
    path('browse/<str:tk>/', views.browse, name="browse"),
    path('register/', views.register_user, name="register-user"),
    path('login/', views.login_user, name="login-user"),
    path('logout/', views.logout_user, name="logout-user"),
    path('activate-user/<uidb64>/<token>/', views.activate_user, name='activate'),
    path('create-post/<str:tk>/', views.createPost, name="create-post"),
    path('profile/<str:pk>/', views.userProfile, name='user-profile'),
    path('settings/', views.userSettings, name='user-settings'),
] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)

Things I have tried/found out

  • settings the action of the form to {% url ‘user-settings’ %} instead of "" but the same outcome would happen, plus the POST request would go through, so that isn’t the problem
  • getting the items directly out of request.FILES, but that didn’t work because they were just null when I took them out
  • I don’t get a error message when I press submit, but my stuff also does not update

If anyone is able to help me out with this I would really appreciate it.

Asked By: Ianis Donica

||

Answers:

As @Demetris already suggested in the above comment you should use enctype="multipart/form-data" in the HTML form so:

{% extends 'main.html' %}

{% block content %}
    <form action="" method="POST">    
        {% csrf_token %}
        {{ form.as_p }}
        <input type="submit" name="user-settings-save" value="submit">
    </form>
{% endblock content %}

Note: You can remove the empty action="" attribute from HTML form since always takes current page route.

Note: Function based views are generally written in snake_case not cascalCase, so it is better to rename it as user_settings from userSettings.

Answered By: Sunderam Dubey