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.
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 django 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
.
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.
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 django always takes current page route.
Note: Function based views are generally written in
snake_case
notcascalCase
, so it is better to rename it asuser_settings
fromuserSettings
.