How can I allow users to edit their profiles in Django? - python

I have a model in models.py like this:
class UserProfile(models.Model):
user = models.OneToOneField(User, on_delete=models.DO_NOTHING)
phone_number = models.CharField(max_length=50, default='')
Birthday = models.CharField(max_length=50, default='')
city = models.CharField(max_length=50, default='')
school = models.CharField(max_length=100, default='')
course = models.CharField(max_length=50, default='')
I want to allow my users to make edits, so I made a function like this in my views.py:
if request.method == 'POST':
profil = UserProfile.objects.get(user=request.user)
profil.phone_number = models.CharField(max_length=50, default='')
profil.Birthday = models.CharField(max_length=50, default='')
profil.city = models.CharField(max_length=50, default='')
profil.school = models.CharField(max_length=100, default='')
profil.course = models.CharField(max_length=50, default='')
profil.save()
return redirect('profile')
return render(request, 'edit_profile.html')
My template is:
<form action="." method="post">
{% csrf_token %}
Phone Number:
<input type="text" name="phone_number" value="{{ profil.phone_number }}" /><br />
Birthday:
<input type="text" name="Birthday" value="{{ profil.Birthday }}" /><br />
city:
<input type="text" name="city" value="{{ profil.city }}" /><br />
school:
<input type="text" name="school" value="{{ profil.school }}" /><br />
course:
<input type="text" name="course" value="{{ profil.course }}" /><br />
<input type="submit" value="Save Changes" name="save" />
<input type="reset" value="Cancel" name="cancel" />
<br/>
</form>
I do not know why, but after filling the form I get an error saying page not found. And if I check the existing user profile nothing got updated. Help please.

you have an error
profil = UserProfile.objects.get(user=request.user)
profil.phone_number = models.CharField(max_length=50, default='')
you get an UserProfile object and then instead of saving str into phone_number you try to save an object models.CharField.
use ModelForm to achieve what you need.
class UserProfileForm(forms.ModelForm):
class Meta:
model = UserProfile
fields = '__all__'
then in your view you can use:
userprofile_form = UserProfileForm(request.POST if request.POST else None, instance = UserProfile.objects.get(user=request.user))
if request.method == 'POST':
if form.is_valid():
form.save()
return redirect('profile')
return render(request, 'edit_profile.html', context={'userprofile_form': userprofile_form)
and in html use:
<form action="." method="post">
{% csrf_token %}
Phone Number: {{ userprofile_form.phone_number }}
Birthday: {{ userprofile_form.Birthday }}
city: {{ userprofile_form.city }}
school: {{ userprofile_form.school }}
course: {{ userprofile_form.course }}
<input type="submit" value="Save Changes" name="save" />
<input type="reset" value="Cancel" name="cancel" />
<br/>
</form>
or just
<form action="." method="post">
{% csrf_token %}
{{ userprofile_form }}
<input type="submit" value="Save Changes" name="save" />
<input type="reset" value="Cancel" name="cancel" />
<br/>
</form>
if you want to use upload files, don't forget to put your files into form you can do it
UserProfileForm(request.POST, request.FILES, instance = UserProfile.objects.get(user=request.user))
and in html you need to put <form enctype="multipart/form-data" method="post" action="...">

Reproduce these steps, you might need slight modifications:
1. Create a UserEditForm
in forms.py
from .models import UserProfile
from django.forms import ModelForm
class UserEditForm(ModelForm):
class Meta:
model = UserProfile
fields = '__all__' # or ['phone_number', 'Birthday', 'city', 'only_fields_you_want_to_edit']
2. Create a View:
in views.py
from django.shortcuts import render, HttpResponseRedirect, get_object_or_404
from django.urls import reverse
from django.forms.models import model_to_dict
from .models import UserProfile
from .forms import UserEditForm
def userEdit(request, user_id):
user = get_object_or_404(Question, pk=user_id)
if request.method == "GET":
form = UserEditForm(initial=model_to_dict(user))
return render(request, 'yourapp/useredit_form.html', {'form':form)
elif request.method == "POST":
form = UserEditForm(request.POST, instance=user)
if form.is_valid():
form.save()
return HttpResponseRedirect(reverse('user_profile', kwargs={'uid':user.id}))
else:
return HttpResponseRedirect(reverse('some_fail_loc'))
3. Create template
in yourapp/useredit_form.html
<form method="POST">
{% csrf_token %}
{{form}}
<button type="submit">Submit</button>
</form>
4. Set a URL:
in urls.py
urlpatterns += [
path('edit_user/<int:user_id>/', views.userEdit, name='user_edit'),
]
Now try visiting yourapp.com/edit_user/1. You are good to go. :D

Related

IntegrityError at /update_dept/1/ NOT NULL constraint failed: main_department.dept_name

I am creating a simple django models of doctors and department. there is not link between them and when I try to update the department then it is show me this error IntegrityError at /update_dept/1/ NOT NULL constraint failed: main_department.dept_name this error is new for me. I check other similar question also but didn't get much. so pls help me.
here is my view.py file
from django.shortcuts import render
from .forms import Doctorslist,Departmentform
from .models import Department, Doctor
from django.shortcuts import redirect
from django.views.generic import (CreateView, DetailView, UpdateView, ListView, TemplateView, DeleteView)
from django.contrib.messages import constants as messages
import os
# Create your views here.
def add_show(request):
form = Doctorslist()
if request.method == "POST":
form = Doctorslist(request.POST, request.FILES)
form.save()
return redirect('/')
else:
form = Doctorslist()
stud = Doctor.objects.all
context = {'form':form,
'stu':stud
}
return render(request, 'main/index.html', context)
def update_data(request, id):
prod = Doctor.objects.get(id=id)
if request.method == "POST":
prod.doc_image = request.FILES['doc_image']
prod.kycdocument = request.FILES['kycdocument']
prod.name = request.POST.get('name')
prod.phone_number = request.POST.get('phone_number')
prod.email = request.POST.get('email')
prod.city = request.POST.get('city')
prod.speciality = request.POST.get('email')
prod.save()
messages.success(request, "Product Updated Successfully")
return redirect('/')
context = {'prod':prod}
return render(request, 'main/update_doc.html', context)
def delete_data(request,id):
if request.method =='POST':
pi = Doctor.objects.get(pk = id)
pi.delete()
return redirect('/')
def add_show_dept(request):
form = Departmentform()
if request.method == "POST":
form = Departmentform(request.POST)
form.save()
return redirect('/')
else:
form = Departmentform()
dept = Department.objects.all
context = {'form':form,
'stu':dept
}
return render(request, 'main/pages-profile.html', context)
def update_dept_data(request, id):
prod = Department.objects.get(id=id)
if request.method == "POST":
prod.dept_name = request.POST.get('dept_name')
prod.dept_Email = request.POST.get('dept_Email')
prod.save()
messages.success(request, "Product Updated Successfully")
return redirect('/')
context = {'prod':prod}
return render(request, 'main/update_dept.html', context)
here is model.py
from django.db import models
from phonenumber_field.modelfields import PhoneNumberField
import os
# Create your models here.
import datetime
def get_file_path(request, filename):
filename_original = filename
nowTime = datetime.datetime.now().strftime('%Y%m%d%H:%M:%S')
filename = "%s%s" % (nowTime, filename_original)
return os.path.join('uploads/', filename)
class Doctor(models.Model):
name = models.CharField(max_length=20)
phone_number = PhoneNumberField(null=False, blank=False, unique=True)
email = models.EmailField(max_length = 100)
city = models.CharField(max_length=100)
speciality = models.CharField(max_length=50)
doc_image = models.ImageField(upload_to = get_file_path)
kycdocument = models.ImageField(upload_to = get_file_path, null = True, blank = True)
class Department(models.Model):
dept_name = models.CharField(max_length=20)
dept_Email = models.EmailField(max_length=100)
dept_password = models.CharField(max_length=200)
here is forms.py file
from django import forms
from phonenumber_field.modelfields import PhoneNumberField
from .models import Doctor,Department
class Doctorslist(forms.ModelForm):
class Meta:
model = Doctor
fields = ('name','phone_number','email', 'city', 'speciality', 'doc_image', 'kycdocument')
# widgets = {
# 'name': forms.TextInput(attrs = {'class': 'form-control'}),
# 'email': forms.EmailInput(attrs={'class': 'form-control'}),
# 'city': forms.CharField(attrs={'class': 'form-control'}),
# 'speciality': forms.CharField(attrs={'class': 'form-control'}),
# }
class Departmentform(forms.ModelForm):
class Meta:
model = Department
fields = ('dept_name','dept_Email','dept_password')
widgets = {'dept_password': forms.PasswordInput()}
here is update_dept.html file
{% extends 'base.html' %}
{% block content %}
<div class="row justify-content-center">
<div class="col-md-8">
<div class="card">
<div class="card-header">
<h2 class="fw-bold">Edit Product</h2>
</div>
<div class="card-body">
<form action="" method="POST" enctype="multipart/form-data">
{% csrf_token %}
<div class="mb-3">
<label for="" class="form-label">Name</label>
<input type="text" Required name="name" value="{{ prod.dept_name }}" class="form-control">
</div>
<div class="mb-3">
<label for="" class="form-label">Email</label>
<input type="text" Required name="price" value="{{ prod.dept_Email }}" class="form-control">
</div>
<button type="submit" class="btn btn-warning">Update</button>
</form>
</div>
</div>
</div>
</div>
{% endblock %}
Your HTML form uses the wrong names, and therefore request.POST does not contain any entries like dept_name and dept_Email. You should specify name="dept_name" instead of name="name" and name="dept_Email" instead of name="price":
<div class="mb-3">
<label for="" class="form-label">Name</label>
<input type="text" Required name="dept_name" value="{{ prod.dept_name }}" class="form-control">
</div>
<div class="mb-3">
<label for="" class="form-label">Email</label>
<input type="text" Required name="dept_Email" value="{{ prod.dept_Email }}" class="form-control">
</div>
That being said, I would strongly advise that you use a ModelForm, you can make a second ModelForm for the department where you leave out the dept_password.
You can see the Rendering fields manually section of the documentation that shows how you can render you Django form with custom HTML.

How to edit user's profile view with django

I am making a form in which the user can edit their profile, so currentley I have 2 forms, one that edits the User model(first_name, Username and Email) and other one that edits the Profile model(biography). The problem is that everytime I edit, just the User model is the one that gets saved while the Profile model doesnt. I think that the error is on the views.py file.
views.py
def edit_profile(request):
if request.method == 'POST':
form = EditProfileForm(request.POST, instance=request.user)
form1 = UpdateProfileForm(request.POST, instance=request.user)
if form.is_valid:
form.save()
form1.save()
return redirect('profile')
else:
form = EditProfileForm(instance=request.user)
form1 = UpdateProfileForm(instance=request.user)
args = {
'form': form,
'form1': form1,
}
return render(request, 'profile-edit.html', args)
forms.py
class EditProfileForm(UserChangeForm):
class Meta:
model = User
fields = (
'first_name',
'username',
'email',
)
exclude = ('password',)
class UpdateProfileForm(forms.ModelForm):
class Meta:
model = Profile
fields = (
'bio',
'profile_pic',
)
exclude = ('user',)
models.py
class Profile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
bio = models.CharField(max_length=400, default=1)
def __str__(self):
return f'{self.user.username} Profile'
profile-edit.html (I replaced the {{form.as_p}} and {{ form1.as_p }} to the following html code)
<form method="post" enctype="multipart/form-data">
{% csrf_token %}
<div class="edit-profile">
<h3>Name</h3>
<input type="text" name="first_name" value="{{ user.first_name }}" maxlength="30" id="id_first_name">
<h3>Username</h3>
<input type="text" name="username" value="{{ user.username }}" maxlength="150" required="" id="id_username">
<h3>Bio</h3>
<input type="text" name="bio" value="{{ user.profile.bio }}" maxlength="400" id="id_bio">
<h3>Email</h3>
<input type="email" name="email" value="{{ user.email }}" maxlength="254" id="id_email">
<button type="submit">Submit</button>
</div>
</form>
I found the error on my code, i missed to pass the .profile from the model in the views.py file
Bad
form1 = UpdateProfileForm(request.POST, instance=request.user)
Good
form1 = UpdateProfileForm(request.POST, instance=request.user.profile)

Django forms error - That choice is not one of the available choices

I'm trying to create a custom messaging platform between users. For some reason it says that my form is not valid when I submit it, and when I print the error with print(messageform.errors), I get:
<ul class="errorlist"><li>receiver<ul class="errorlist"><li>Select a valid choice. That choice is not one of the available choices.</li></ul></li></ul>
This is strange because I don't believe that I'm using a dropdown anywhere in the form. Does anyone know why this might be the case?
forms.py
class MessageForm(forms.ModelForm):
class Meta:
model = Message
fields = ['text', 'receiver']
html file
<form action="" method="post">
{% csrf_token %}
<input type="text" name="text" value="" />
<label for="text">Enter your message here</label><br/>
<input type="text" name="receiver" value="" />
<label for="receiver">id of receiver</label><br/>
<input type="submit" value="Send" />
</form>
models.py
class Message(models.Model):
text = models.TextField(max_length=10000, blank=True)
sender = models.ForeignKey(
settings.AUTH_USER_MODEL,
on_delete=models.CASCADE,
null = True,
related_name="sender"
)
receiver = models.ForeignKey(
settings.AUTH_USER_MODEL,
on_delete=models.CASCADE,
null = True,
related_name="receiver"
)
views.py
usermodel = get_user_model()
if request.method == "POST" and not signupform.is_valid():
messageform = MessageForm(request.POST)
print(messageform.errors)
if messageform.is_valid():
receiverid = messageform.cleaned_data['receiver']
newmessage = messageform.save(commit=False)
newmessage.sender = request.user
newmessage.receiver = usermodel.objects.filter(username=receiverid)
newmessage.text = messageform.cleaned_data['text']
new_profile.save()
return HttpResponseRedirect('/profile/')

django template form not saving data

I have a template form and trying to save some data. Upon clicking on the submit button the page just refreshes and nothing gets saved to the database. I don't get any errors on anything.
template
<form action="" method="post" id="salesform">
{% csrf_token %}
<input type="name" class="form-control" id="name" placeholder="Name">
<input type="clinic" class="form-control" id="clinic_name" placeholder="Clinic">
<input type="phone" class="form-control" id="phone" placeholder="Phone">
<input type="email" class="form-control" id="email" placeholder="Email">
<button id="sub" type="submit" class="btn btn-default">Submit</button>
</form>
forms.py
class LeadForm(forms.ModelForm):
name = forms.CharField(max_length=250, required= True,widget=forms.TextInput())
clinic_name = forms.CharField(max_length=250, required= True,widget=forms.TextInput())
phone = forms.CharField(max_length=8, required= True,widget=forms.TextInput(attrs={'type':'number'}))
email = forms.CharField(max_length=250, required= False, widget=forms.TextInput())
class Meta:
model = Lead
fields = ("clinic_name","phone")
views.py
def add_doc_info(request):
d = getVariables(request,dictionary={'page_name': "Doctors",
'meta_desc' : "Sign up "})
if request.method == "POST":
SalesForm = LeadForm(request.POST)
if SalesForm.is_valid():
name = SalesForm.cleaned_data['name']
clinic_name = SalesForm.cleaned_data['clinic_name']
phone = SalesForm.cleaned_data['phone']
email = SalesForm.cleaned_data['email']
#Saving to database
lead = Lead(name=name, clinic_name=clinic_name, phone=phone, email=email)
lead.save()
else:
SalesForm = LeadForm()
return render(request, 'm1/add_doc_info.html', d, context_instance=RequestContext(request))
models.py
class Lead(models.Model):
name = models.CharField(max_length=1300)
clinic_name = models.CharField(max_length=1300)
phone = models.IntegerField()
email = models.EmailField(blank = True)
submitted_on = models.DateField(auto_now_add=True)
def __unicode__(self):
return u"%s %s" % (self.clinic_name, self.phone)
Almost certainly the form is not valid, but you're not using it in your template so there is no way for it to display errors, or redisplay itself with partially-filled fields.
The Django documentation is fairly explicit on this, so I don't know why you have done something different. Pass the form into your context:
d['form'] = SalesForm
return render(request, 'm1/add_doc_info.html', d)
and use it in the template:
{{ form.errors }}
<form action="" method="post" id="salesform">
{% csrf_token %}
{{ form.name }}
{{ form.clinic_name }}
{{ form.phone }}
{{ form.email }}
<button id="sub" type="submit" class="btn btn-default">Submit</button>
</form>
(Note also you've unnecessarily defined all the fields explicitly in the form, but also stated you are only using two of them in the meta class; also your is_valid block is mostly unnecessary as you can just call form.save() directly. Again, all this is shown fully in the documentation.)

ModelChoiceField django

I have created a Django form to get the data from user and search that given data in database models.
But i am not able to use the dropdown functionality correctly. I have used ModelChoiceField but I am getting it empty.
I have three fields(forms.py) which i am searching in the database.
models.py
class Release(models.Model):
number = models.CharField(max_length=50,unique=True)
notes = models.CharField(max_length=50)
changes = models.CharField(max_length=50)
def __unicode__(self):
return unicode(self.number)
class Metamodule(models.Model):
name = models.CharField(max_length=50,unique=True)
version = models.IntegerField(default=0)
release = models.ForeignKey(Release,related_name="num")
createdate = models.DateField(auto_now=True, null=True)
createdby = models.CharField(max_length=50)
def __unicode__(self):
return unicode(self.name)
class Module(models.Model):
name = models.CharField(max_length=50,unique=True)
version = models.IntegerField(default=0)
metamodule = models.ForeignKey(Metamodule,related_name="metaname")
createdate = models.DateField(auto_now=True, null=True)
changes = models.CharField(max_length=50)
def __unicode__(self):
return unicode(self.name)
forms.py
class ModuleForm(forms.Form):
release_num = forms.ModelChoiceField(queryset=Release.objects.all().values('number'),empty_label='Pick a Release')
metamodule_name = forms.CharField(max_length=50)
module_name = forms.CharField(max_length=50)
views.py
from django.shortcuts import render
from search.forms import ModuleForm
from django.http import HttpResponse
from search.models import Module,Metamodule,Release
def searchview(request):
if request.method == 'GET':
form = ModuleForm(request.GET)
if form.is_valid():
release_num = form.cleaned_data['release_num']
metamodule_name = form.cleaned_data['metamodule_name']
module_name = form.cleaned_data['module_name']
results = Module.objects.filter(metamodule__release__number=release_num).filter(metamodule__name=metamodule_name).filter(name=module_name)
return render(request,'search/search_result.html',{'form': form, 'results': results})
else:
form = ModuleForm()
return render(request, 'search/search_form.html',{'form': form})
search_form.html
<html>
<head>
<title>Search</title>
</head>
<body>
{% if error %}
<p style="color: red;">Please submit a search term.</p>
{% endif %}
<form action="/search/" method="get">
<select name="release_num">
{% for release_num in release_num %}
<option value="{{ release_num.number }}">{{ release_num.number }}</option>
{% endfor %}
</select>
<p><label for="metamodule_name">Metamodule:</label>
<input type="text" name="metamodule_name">
<p><label for="module_name">Module:</label>
<input type="text" name="module_name">
<input type="submit" value="Search">
</form>
</body>
</html>
try in the search_form.html:
<form action="/search/" method="get">
{{ form.release_num }}
{{ form.metamodule_name }}
{{ form.module_name }}

Categories