Django custon form with validate - django

I have some problem with the form and Django.
I would like to do a custom (in column and with style) form from a model. But after few hours to try I thinks it's not possible.
So I decide to create not a forms.ModelForm but a forms.Form, in order to custom my form. But in this way i can't keep the validations...
And last thing I try, it in the template file to write a validation manually, it's work but when I submit my form with error, and when it's refresh, all the data are loose, and I see just the error message...
So it make me crazy... I just would like to do a nice form with django...
Thanks in advance
forms.py
class PatienceForm(forms.ModelForm):
class Meta:
model = Patience
fields = ('nom', 'prenom', 'age', 'email')
template.html
<form method="POST" accept-charset="utf-8">
{% csrf_token %}
<p><label for="id_nom">Nom :</label> <input type="text" name="nom" maxlength="200" required id="id_nom"></p>
<p><label for="id_prenom">Prenom :</label> <input type="text" name="prenom" maxlength="200" required id="id_prenom"></p>
<p><label for="id_age">Age :</label> <input type="number" name="age" required id="id_age"></p>
<p><label for="id_email">Email :</label> <input type="email" name="email" maxlength="254" required id="id_email"></p>
{% for err in form.email.errors %}
{{err}}
{% endfor %}
<button type="submit" class="save btn btn-default">Save</button>
view.py
def post_essaie(request):
if request.method == "POST":
form = PatienceForm(request.POST)
if form.is_valid():
logging.info('Hello')
post = form.save(commit=False)
post.published_date = timezone.now()
post.save()
return render(request, 'blog/succes.html')
return render(request, 'blog/teste.html', {'form': form})
else:
form = PatienceForm()
return render(request, 'blog/teste.html', {'form': form})
Thanks in advance for your help

for your form.py :
class PatienceForm(forms.Form):
nom = forms.CharField(max_length=200,label='Nom')
prenom = forms.CharField(max_length=200)
age = forms.integerField(max_length=200)
email = forms.EmailField(max_length=254)
# use clean to verify your form
def clean(self):
cleaned_data = super(ContactForm, self).clean()
nom = cleaned_data.get('nom')
prenom = cleaned_data.get('prenom')
age = cleaned_data.get('age')
email = cleaned_data.get('email')
if not name and not email and not message:
raise forms.ValidationError('le formulaire est vide')
in your views.py you can use :
from django.shortcuts import render
from .forms import ContactForm
def post_essaie(request):
if request.method == 'POST':
form = PatienceForm(request.POST)
if form.is_valid():
logging.info('Hello')
nom = form.cleaned_data['nom']
prenom = form.cleaned_data['prenom']
age = form.cleaned_data['age']
email = form.cleaned_data['email']
# here create your entry with all the data from your form then add
# your published_date
post = Patience(nom=nom, prenom=prenom, age=age,
email=email, published_date = timezone.now())
post.save()
return render(request, 'blog/succes.html')
else:
form = PatienceForm()
return render(request, 'blog/teste.html', {'form': form})
Voila Bonne journée !!

Related

Django Edit Profile View not saving new email value

I am (attempting to) implement the ability for a user to edit and update their email address on their profile page. I am getting no errors when doing this end to end but the new email is not being saved to the DB.
Everything seems to be working, even the redirect to the profile page in the edit_profile function, but the save() doesn't seem to be working, the users email doesn't update and when I am redirected back to the profile page, the email is still the current value.
Thanks!
Model:
class CustomUser(AbstractUser):
email = models.EmailField(_('email address'), unique=True)
is_pro = models.BooleanField(default=False)
is_golfer = models.BooleanField(default=False)
def __str__(self):
return self.email
Form
class EditProfileForm(forms.Form):
email = forms.EmailField(
label='', widget=forms.TextInput(attrs={'class': 'form-field'}))
View
#login_required
def edit_profile(request):
if request.method == "POST":
form = EditProfileForm(request.POST)
if form.is_valid():
email = form.cleaned_data["email"]
user = CustomUser.objects.get(id=request.user.id)
user.save()
return redirect("typeA", username=user.username)
else:
form = EditProfileForm()
return render(request, "registration/edit_profile.html", {'form': form})
URLS
urlpatterns = [
path('type_a_signup/', ASignUpView.as_view(), name='a_signup'),
path('type_b_signup/', BSignUpView.as_view(), name='b_signup'),
path('login/', LoginView.as_view(), name='login'),
path('password_reset', PasswordResetView.as_view(), name='password_reset'),
path('typea/<username>/', typeA, name='typeA'),
path('typeb/<username>/', typeB, name='typeB'),
path('login_success/', login_success, name='login_success'),
path('edit_profile/', edit_profile, name='edit_profile'),
]
Template
<div class="container">
<div class="form-container">
<h2>Edit profile</h2>
<form method="post" enctype="multipart/form-data">
{% csrf_token %}
<div>
{{ form.email.label_tag }}
<input type="text" class="form-control {% if form.email.errors %}is-invalid{% endif %}" id="id_email"
name="email" value='{{ form.email.value|default:user.email }}'>
{% if form.email.errors %}
<div>{{ form.email.errors }}</div>
{% endif %}
</div>
<button type="submit">Submit</button>
</form>
<br>
</div>
You never set the email field of the object. You should set this with:
#login_required
def edit_profile(request):
if request.method == "POST":
form = EditProfileForm(request.POST)
if form.is_valid():
email = form.cleaned_data["email"]
user = request.user
user.email = email # 🖘 set the email field
user.save()
return redirect("typeA", username=user.username)
else:
form = EditProfileForm()
return render(request, "registration/edit_profile.html", {'form': form})
You should only redirect in case the form is successful. If it is not, Django will rerender the form with the errors.

Fill input field of foreignkeyfield from database in Django

I am using a foreignkey field of a model as an input field in the html form because I want a user input if the value is not present in the database. So I just gave an input tag and in views I take the value and assign it to the form field. Now if the userprofile is already created then the pincode value will be there. How can I prepopulate the input field in the html with the value from the database?
profile.html
<form method="POST" id="userProfileForm" enctype="multipart/form-data">
{% csrf_token %}
.
.
.
<div>
<label for="input_pincode">Pincode</label>
<input id="input_pincode" type="text" name="input_pincode">
</div><br>
.
.
.
</form>
models.py
class UserProfile(models.Model):
.
.
.
pincode = models.ForeignKey(Pincode, models.SET_NULL, blank=True, null=True)
forms.py
class UserProfileUpdateForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
super(UserProfileUpdateForm, self).__init__(*args, **kwargs)
for visible in self.visible_fields():
visible.field.widget.attrs['class'] = 'form-control'
class Meta:
model = UserProfile
fields = ['pincode', other_fields]
views.py
def profile(request):
if request.method == 'POST':
u_form = UserUpdateForm(request.POST, instance=request.user)
up_form = UserProfileUpdateForm(request.POST, request.FILES, instance=request.user.userprofile)
if u_form.is_valid() and up_form.is_valid():
u_form.save()
uncommitted_up_form = up_form.save(commit=False)
if request.POST['city']:
pin = Pincode.objects.get_or_create(city_id=request.POST['city'], pincode=request.POST['input_pincode'])[0]
uncommitted_up_form.pincode = pin
#other logic
uncommitted_up_form.save()
messages.success(request, f'Your profile has been updated!')
return redirect('profile')
Here in the html file I want to show the value of userprofile.pincode.name in the input_pincode box. How can I do that?
This is an example of how to show the value of userprofile.pincode.name in the input_pincode box. You can try like this.
in views.py
name = userprofile.pincode.name
return render(request, "profile.html", {"name ": name }) OR return render(request,
"profile.html", {"name ": userprofile.pincode.name})
in HTML template
<form method="POST" id="userProfileForm" enctype="multipart/form-data">
{% csrf_token %}
<div>
<label for="input_pincode">Pincode</label>
<input id="input_pincode" value="{{name}}" type="text" name="input_pincode">
</div><br>
</form>

Replacing a file in django

I have a standard Form to edit an object that has a file field in it. When I add a new profile, everything works fine, but when I want to modify a field, then problems happen: when I don't include request.FILES, all fields get retrieved in the form and can be updated with no problems, except the avatar (filefield), but when I add the request.FILES, fields are no longer retrieved in the inputs, and the form is not valid. What am I doing wrong?
models.py:
from django.db import models
class Profile(models.Model):
name = models.CharField(max_length=45)
email = models.EmailField()
avatar = models.FileField(upload_to="avatars/")
def __str__(self):
return self.name
forms.py:
from django import forms
from .models import Profile
class EditUserForm(forms.ModelForm):
class Meta:
model = Profile
fields = ["name", "email", "avatar"]
profile.html:
<form method="POST">
{% csrf_token %}
<div class="col-md-12">
<div class="row border m-3 p-5">
<div class="col-md-6">Name</div>
<div class="col-md-6">{{ form.name }}</div>
</div>
<div class="row border m-3 p-5">
<div class="col-md-6">Email</div>
<div class="col-md-6">{{ form.email }}</div>
</div>
<div class="row border m-3 p-5">
<div class="col-md-6">Avatar</div>
<div class="col-md-6">
<img src="{{ profile.avatar.url }}" width="100rem" />
{{ form.avatar }}
</div>
</div>
<div class="row">
<button type="submit" class="btn btn-success">Save</button>
</div>
</div>
</form>
views.py:
def profile(request, pk):
profile_instance = Profile.objects.get(id=pk)
form = EditUserForm(request.POST, request.FILES, instance = profile_instance)
context = {
'profile': profile_instance,
'form': form,
}
if request.method == "POST":
if form.is_valid():
profile = form.save(commit=False)
profile.save()
else:
print("form not valid")
else:
return render(request, "app/profile.html", context)
return render(request, "app/profile.html", context)
Special thank's to #bruno desthuilliers and #dirkgroten.
Here is the answer to solve the 2 problems:
def profile(request, pk):
if request.method == 'POST':
form = EditUserForm(request.POST, request.FILES, instance = Profile.objects.get(id=pk))
if form.is_valid():
profile = form.save(commit=False)
profile.save()
return redirect('profile', pk)
else:
form = EditUserForm(instance = Profile.objects.get(id=pk))
context = {
'profile': Profile.objects.get(id=pk),
'form': form,
}
return render(request, "app/profile.html", context)
Try refactoring the code as follows: (edit it if I missed something. After form.is_valid, the same form should be sent in the context to display the errors.
def profile(request, pk):
profile_instance = Profile.objects.get(id=pk)
form = EditUserForm(instance = profile_instance)
if request.method == "POST":
form = EditUserForm(request.POST, request.FILES, instance = profile_instance)
if form.is_valid():
profile = form.save(commit=False)
profile.save()
form = EditUserForm(instance = profile_instance)
context = {
'profile': profile_instance,
'form': form,
}
return render(request, "app/profile.html", context)

How to get form input using forms.Form into a postgres database?

Here is my code:
My forms.py looks like:
from django import forms
class SimpleForm(forms.Form):
website = forms.URLField(required=True,
widget=forms.TextInput(
attrs={'placeholder': "http://www.example.com"}))
email = forms.EmailField(required=True,
widget=forms.TextInput(
attrs={'type': 'email',
'placeholder': "john.doe#example.com"
}))
My views.py looks like:
from django.shortcuts import render, redirect
from django.template import loader
from .forms import SimpleForm
def simple_form(request):
if request.method == 'POST':
form = SimpleForm(request.POST)
if form.is_valid():
website = form.cleaned_data['website']
email = form.cleaned_data['email']
return render(request, 'some_page.html')
else:
form = SimpleForm()
return render(request, 'some_other_page.html', {'form': form})
As for my HTML form, it looks like the following below:
<form method="post">
{% csrf_token %}
<div class="some-class">
<label for="website">Enter Your Site:</label>
<!-- <input type="text" id="website" placeholder="http://www.example.com" name="website" /> -->
{{ form.website }}
<label for="email">Enter Your Email:</label>
<!-- <input type="text" id="email" placeholder="john.doe#example.com" name="website" /> -->
{{ form.email }}
</div>
<div class="some-other-class">
<div class="another-class">
<button name="submit">Submit</button>
</div>
</div>
</form>
My question is, how do I get the input for this form into a table in my postgres database?
You could make a ModelForm instead of a form and turn your form into a Model:
class SimpleModel(models.Model):
website = models.URLField(
required=True,
widget=forms.TextInput(attrs={'placeholder': "http://www.example.com"}))
email = models.EmailField(
required=True,
widget=forms.TextInput(attrs={'type': 'email', 'placeholder': "john.doe#example.com"}))
class SimpleForm(forms.ModelForm):
class Meta:
model = SimpleModel
fields = ['website', 'email']
Follow the link and look at the docs, you can make it very abstract, Django can handle most things for u.
When saving you can do a form.save() as seen here
It is wise to first check the form by doing form.is_valid()
Example view:
def simple_form(request):
if request.method == 'POST':
form = SimpleForm(request.POST)
if form.is_valid():
form.save()
return render(request, 'some_page.html')
form = SimpleForm()
return render(request, 'some_other_page.html', {'form': form})
You can also follow this tutorial to get to know the Django basics
Sounds like you could use the basics ;)

Django model form for user profile won't pre-populate

I've made a profile model in models.py:
class Profile(models.Model):
user = models.OneToOneField(User)
title = models.CharField(max_length=20, default='title')
firstname = models.CharField(max_length=40, default='firstname')
lastname = models.CharField(max_length=40, default='lastname')
blurb = models.CharField(max_length=500, default='tell us about yourself')
#work out how to make filename equal the username
pic = models.ImageField(default="static/profile/blank.png", upload_to='static/profile/%d%m%y.jpg') #+ user.pk + '.jpg')
def __unicode__(self):
return self.user.username
and here is the view for a page to edit the profile of a logged in user:
def editprofile(request):
u_p = request.user.profile
template = loader.get_template('registration/editprofile.html')
if request.method == 'POST':
form = ProfileForm(request.POST, instance=u_p)
if form.is_valid():
form.save()
else:
# todo
None
else:
#todo
context = RequestContext(request, {'form': form})
return HttpResponse(template.render(context))
The template fragment reads:
<form method="POST" action=".">
{% csrf_token %}
<div class="regformout">
<div class="regform">
{% for field in form %}
<div class='cell'> {{ field.label_tag }} </div>
<div class='nogin'> {{ field.errors }} </div>
<div class='cell'> {{ field }} </div>
{% endfor %}
</div>
</div>
<input class="btn btn-large btn-primary" type="submit" value="Save Your Profile" ></input>
</form>
I want the form fields to automatically populate with the data for the current user on the corresponding page for editing the profile. However, no matter what I try I cannot make this happen. What am I doing wrong here?
Your main problem is you are only populating the form if the user hits the submit button, so when the view is requested initially, your form is empty.
from django.shortcuts import render, redirect
def editprofile(request):
u_p = request.user.profile
form = ProfileForm(request.POST or None, instance=u_p)
if request.method == 'POST':
if form.is_valid():
form.save()
return redirect('/')
return render(request,
'registration/editprofile.html', {'form': form})