Cannot saving form in django - django

So i'm using the auth.models.user to create user model and by default it's passing ('first_name', 'last_name', 'username', 'email', 'password1', 'password2'). and the forms.py:
class UserSignUpForm(UserCreationForm):
class Meta:
fields = ('first_name','last_name','username', 'email', 'password1', 'password2')
model = user
def __init__(self,*args,**kwargs):
super().__init__(*args,**kwargs)
self.fields['username'].label = 'Username'
self.fields['email'].label = "Email Address"
i try to allowing user to edit their personal information from all avaliable fields in UserSignUpForm, except the password fields. so i created this views.py (function based view):
def edit_account(request):
user = request.user
form = UserSignUpForm(instance=user)
if request.method == 'POST':
form = UserSignUpForm(request.POST, instance=user,)
if form.is_valid():
form = UserSignUpForm(instance=user)
form.save()
messages.success(request, 'Your account has been updated.')
return redirect('/dashboard/profile/')
context = {'editform':form}
return render(request, 'accounts/updateaccounts.html', context)
tried submit the specific field form like{{editform.first_name}} after passsing it in the html page (because i dont want to user be able edit their password) but it still not update/saving the new user data. is there any method so it can be save? thanks

In the html file, have you tried printing the form errors to see what's happening? try this:
<form method = "POST">
{% csrf_token %}
{% if form.errors %}
{% for field in form %}
{% for error in field.errors %}
<div class="alert alert-danger">
<strong>{{ error|escape }}</strong>
</div>
{% endfor %}
{% endfor %}
{% for error in form.non_field_errors %}
<div class="alert alert-danger">
<strong>{{ error|escape }}</strong>
</div>
{% endfor %}
{% endif %}
</form>
Also, you have a " form = UserSignUpForm(instance=user)" outside of the if request.POST...
You also have a " form = UserSignUpForm(instance=user)" after form is valid.

Related

Get error message from imported/external validator to print django

I am trying to build a simple user registration page. I want it to include a captcha for validation purposes. I am using django-simple-captcha for this purpose. (If there's a better library, tell me...)
So far everything is working great, EXCEPT that when a captcha is incorrect the user is not notified--they are simply returned to the registration screen. How can I get a specific ValidationError message printed when the captcha is invalid? (I'm also using django-crispy-forms, if that makes any difference)
template:
{% extends "base.html" %}
{% load crispy_forms_tags %}
{% block content %}
<div class="content-section">
<form method="POST">
{% csrf_token %}
<fieldset class="form-group">
<legend class="border-bottom mb-4">Registration</legend>
{{ form|crispy }}
</fieldset>
<div class="form-group">
<button class="btn btn-outline-info" type="submit">Sign Up</button>
</div>
</form>
<div class="border-top pt-3">
<small class="text-muted">Already Have An Account?<a class="ml-2" href="{% url 'login' %}">Log in</a></small>
</div>
</div>
{% endblock content %}
form model:
class UserRegisterForm(UserCreationForm):
email = forms.EmailField(validators=[validate_email])
captcha = CaptchaField()
class Meta:
model = User
fields = ['username', 'email', 'password1', 'password2'] # including 'captcha here didn't seem to make a difference
and the view:
def register(request):
if request.method == 'POST':
form = UserRegisterForm(request.POST)
if form.is_valid():
*do unrelated things*
return redirect('login')
else:
form = UserRegisterForm()
return render(request, 'register-template-url', {'form': form})
from simplecaptcha.fields import CaptchaField----
if you are importing CaptchaField like this it will work. If it not works just simply do 1 change as shown below
from simplecaptcha import captcha,captchaform
#captchaform('captcha')
class UserRegisterForm(UserCreationForm):
email = forms.EmailField(validators=[validate_email])
captcha = CaptchaField()
class Meta:
model = User
fields = ['username', 'email', 'password1', 'password2','captcha']

How to get value especific from ModelForm field in django framework?

I am creating one web system and need to get one value especific from ModelForm for store in another system, in addition to storing in django. Example: get field "nome" from Model Form for to store in LDAP server
model.py
class Orientado(models.Model):
nome = models.CharField(max_length=100,)
telefone = models.CharField(max_length=20)
email = models.EmailField(max_length=100)
forms.py
class OrientadoForm(forms.ModelForm):
class Meta:
model = Orientado
fields = ['nome', 'telefone','email']
views.py
def person_new(request):
form = OrientadoForm(request.POST or None, request.FILES or None)
autor = User.objects.get(username=request.user.username)
if form.is_valid():
form.save()
return redirect('person_list')
return render(request, 'person_form.html',{'form': form, 'autor': autor})
html
{% block main %}
<h3>Novo Orientado</h3>
<form method="post" enctype="multipart/form-data">
{% csrf_token %}
{{ form.non_field_errors }}
{{ form.source.errors }}
{{ form.source }}
{{ form|bootstrap }}
<button type="submit" class="btn btn-primary">Salvar</button>
</form>
{% endblock %}

Why Django return form is invalid?

I have a problem whit a function, when I use the tag {{form.image_cliente}} always return a "form is invalid" and don't save nothing but if I use the tag {{form.as_p}} return a form is valid and save the field image_cliente, and I dont know why, I just want to display only the form.image_cliente in the template.
Mys form Cliente:
class ClienteForm(forms.ModelForm):
id_tipo_cliente = forms.ModelChoiceField(queryset=Tipo_cliente.objects.filter(status=1), label="Tipo de cliente" ,empty_label="Seleciona tipo", widget=forms.Select(attrs={'value':'form-control'}))
password = forms.CharField(label="Password", required=False,
widget=forms.PasswordInput)
class Meta:
model = Cliente
exclude = ['status', 'id_usuario_alt', 'fecha_creacion', 'fecha_modificacion', 'fecha_cancelacion']
fields = [
'nombres',
'apellidos',
'usuario',
'password',
'correo_electronico',
'direccion',
'telefono',
'telefono_celular',
'id_tipo_cliente',
'image_cliente',
]
labels = {'nombres':'Nombres', 'apellidos':'Apellidos', 'usuario':'Usuario', 'correo_electronico':'Correo', 'direccion':'Direccion', 'telefono':'Telefono', 'telefono_celular':'Celular', }
widgets = {
'nombres': forms.TextInput(attrs={'class':'form-control'}),
'apellidos': forms.TextInput(attrs={'class':'form-control'}),
'usuario': forms.TextInput(attrs={'class':'form-control'}),
'correo_electronico': forms.TextInput(attrs={'class':'form-control'}),
'direccion': forms.TextInput(attrs={'class':'form-control'}),
'telefono': forms.TextInput(attrs={'class':'form-control'}),
'telefono_celular': forms.TextInput(attrs={'class':'form-control'}),
'image_cliente':forms.ClearableFileInput(attrs={'multiple': True, 'class':'file', 'data-show-upload':'false', 'data-show-preview':'false'})
}
This is my def function in my views:
def subirIMGCliente(request, pk):
clientes = get_object_or_404(Cliente, pk=pk)
if request.method == 'POST':
form = ClienteForm(request.POST, request.FILES, instance=clientes)
if form.is_valid():
clientes = form.save(commit=False)
if clientes.password == '':
clientes.save(update_fields=['image_cliente'])
print('yes');
return redirect('BackEnd:cliente')
else:
print('form in not valid');
else:
form = ClienteForm(instance=clientes)
return render(request, 'back/Modulo_cliente/imagenes_cliente.html', {'form': form })
My Template
<form method="post" enctype="multipart/form-data">
{% csrf_token %}
<div class="container">
<div class="row">
<div class="col-md-8 col-md-offset-2">
<div class="form-group">
{{form.image_cliente}}
</div>
</div>
</div>
</br>
<br> <div class="row">
<div class="col-md-8 col-md-offset-2">
<button class="btn btn-success" type="submit">Guardar</button>
<span>Regresar</span>
</div>
</div>
</div>
</form>
the following fields are required:
usuario
nombres
direccion
apellidos
id_tipo_cliente
correo_electronico
telefono
telefono_celular
Add a required=False on them like you have on the password field, and you'll be on your way.
You add an instance for the object, and that object has values for all the required form fields, so when you load form.as_p, or any other tag that outputs the entire form, it loads with all the required fields filled out. That way, when the form is submitted, there are no validation errors. Validity checks are done over request.POST and not on the original model instance, so when the form is submitted without some of the required fields, you get validation errors.
To debug these sorts of issues, add a {{form.errors}} somewhere in your template. That's how I found the errors in your form.
It's considered best practice to display all non-field related errors in a list at the top of the form and field-related errors next to each form field.
So you'd add something like this at the top of the template:
<ol>
{% for error in form.non_field_errors %}
<li><strong>{{ error|escape }}</strong></li>
{% endfor %}
</ol>
And something like this for the image_cliente form field:
{% if form.image_cliente.errors %}
<ol>
{% for error in form.image_cliente.errors %}
<li><strong>{{ error|escape }}</strong></li>
{% endfor %}
</ol>
{% endif %}

Edit Model data using ModelForm: ModelForm validation error

I am working on my first django app. I am building an app that allows the user to rate beer. I want my user to be able to edit an entry they've already created. I take them to a ModelForm, and ask for their entry. When the POST method is called, my data is invalid. Here is my model.py:
from django.db import models
class Rating(models.Model):
beer_name = models.TextField()
score = models.DecimalField(max_digits=2, decimal_places=1)
notes = models.TextField(blank=True)
brewer = models.TextField(blank=True)
and forms.py:
from django import forms
from ratings.models import Rating
class RatingForm(forms.ModelForm):
class Meta:
model = Rating
fields = ['beer_name', 'score', 'notes', 'brewer']
Here is the views.py of my edit function:
def edit(request, row_id):
rating = get_object_or_404(Rating, pk=row_id)
if request.method == "POST":
form = RatingForm(request.POST, instance=rating)
if form.is_valid():
form.save()
return redirect(home)
else:
return HttpResponse("Invalid entry.")
else:
context = {'form': rating}
form = RatingForm(instance=rating)
return render(
request,
'ratings/entry_def.html',
context
)
However, every time the POST is called I get an "Invalid entry." HttpResponse, meaning my form.is_valid() is being returned False. Here is my template:
{% extends "base.html" %}
{% block content %}
<div class="container-fluid">
<div class="row">
<div class="col-sm-10 col-sm-offset-1">
<h2>Edit Rating</h2>
<form role="form" method="post">
{% csrf_token %}
<p>Beer Name: <textarea>{{ form.beer_name }}</textarea></p>
<p>Score: <input type="text" name="BeerScore" value="{{ form.score }}"></p>
<p>Notes: <textarea>{{ form.notes }}</textarea></p>
<p>Brewer: <textarea>{{ form.brewer }}</textarea></p>
<p><button type="submit" class="save btn btn-primary">Save</button></p>
<p><button type="reset" class="btn btn-primary">Cancel</button></p>
</form>
</div>
</div>
</div>
{% endblock %}
So when I press my Save button, I am getting the response. Here is my edit url in urls.py:
urlpatterns = [
...
url(r'rating/edit/(?P<row_id>[0-9]+)/$', edit , name='rating-edit'),
]
You're wrapping fields in other fields which don't have name attributes. This is most likely causing the values to be excluded from the request.POST data.
Additionally, Django form fields all have a corresponding HTML widget. So there's really no need to render the HTML by hand, unless you need to.
Change your template code to:
<p>
{{ form.beer_name.label }}: {{ form.beer_name }}
{% if form.beer_name.errors %}
<br />{{ form.beer_name.errors }}
{% endif %}{# repeat for other fields as needed #}
</p>
<p>{{ form.score.label }}: {{ form.score }}</p>
<p>{{ form.notes.label }}: {{ form.notes }}</p>
<p>{{ form.brewer.label }}: {{ form.brewer }}</p>
<p><button type="submit" class="save btn btn-primary">Save</button></p>
<p><button type="reset" class="btn btn-primary">Cancel</button></p>
If you need to change the widget, do so at the form class level:
class RatingForm(forms.ModelForm):
class Meta:
model = Rating
def __init__(self, *args, **kwargs):
super(RatingForm, self).__init__(*args, **kwargs)
self.fields['notes'].widget = forms.Textarea()
This way, Django manages the attributes and binding for you.
Your view can also use some cleanup:
def edit(request, row_id):
rating = get_object_or_404(Rating, pk=row_id)
form = RatingForm(request.POST or None, instance=rating)
if request.method == "POST" and form.is_valid():
form.save()
return redirect(home)
context = {'form': rating}
return render(request, 'ratings/entry_def.html', context)

Django: Only update fields that have been changed in UpdateView

I'm using an UpdateView to update a series of fields. However, I only want fields that have been modified to be saved to the database. If a value was not provided for a field during update process, I want the previous value to be used as the default. If a new value was provided for a field then only that field should be updated. How do I go about accomplishing this?
#views.py
class AccountUpdate(UpdateView):
""" Updates an account; unchanged fields will not be updated."""
context_object_name = 'account'
form_class = UpdateForm
template_name = 'accounts/update_account.html'
success_url = '/accounts/home'
def get_object(self, queryset=None):
return self.request.user
def form_valid(self, form):
clean = form.cleaned_data
#encrypt plain password
form.instance.password = hash_password(clean['password'])
context = {}
self.object = context.update(clean, force_update=False)
return super(AccountUpdate, self).form_valid(form)
#templates
{% extends 'base.html' %}
<title>{% block title %}Update Account{% endblock %}</title>
{% block content %}
{{ account.non_field_errors }}
<div class="errors" style="list-style-type: none;">
{% if account.first_name.errors %}{{ account.first_name.errors }}{% endif %}
{% if account.last_name.errors %}{{ account.last_name.errors }}{% endif %}
{% if account.email.errors %}{{ account.email.errors }}{% endif %}
{% if account.password.errors %}{{ account.password.errors }}{% endif %}
{% if account.username.errors %}{{ account.username.errors }}{% endif %}
</div>
<form action="" name="edit" method="post">
{% csrf_token %}
<ul>
<li>Fullname</li>
<li> {{ form.first_name }}{{ form.last_name }}</li>
<li>Email</li>
<li>{{ form.email }}</li>
<li>Password</li>
<li>{{ form.password }}</li>
<li>Username</li>
<li>{{ form.username }}</li>
</ul>
<ul>
<li><input type="submit" value="update account"></li>
</ul>
</form>
<ul>
<li class="nav">cancel changes</li>
</ul>
{% endblock %}
All the fields are also declared as required in models.py. Currently the form only works if i provide a value for each field.
i'm using a custom hash during update process to encrypt passwords. When i visit the edit page and hit update button, the old password in its current encrypted form gets re-encrypted hence losing the old password
I would handle that by not including password itself in the form. Instead, I would add a new field (something like new_password) to allow entering a new password. Then, in your is_valid method, set the password to the hashed value of that field if there's content.
You should also use the sensitive value filtering tools to prevent user passwords from showing up in emailed error reports.
class UpdateForm(forms.ModelForm):
class Meta:
model = user
fields = ('first_name', 'last_name', 'email', 'username')
new_password = forms.CharField(required=False, widget=forms.widgets.PasswordInput)
And then in your view:
#sensitive_variables('new_password')
#sensitive_post_parameters('new_password')
def form_valid(self, form):
clean = form.cleaned_data
new_password = clean.get('new_password')
if new_password:
#encrypt plain password
form.instance.password = hash_password(new_password)
return super(AccountUpdate, self).form_valid(form)
The easiest way would be to pre-populate the fields with what's already there.
Do this on the template with {{ account.name }} or whatever.