1
I’m still not exactly sure what you’re asking but let’s clean this up a bit.
First off, you need to be leveraging the built-in UserCreationForm
from django.contrib.auth.forms
. Second, never, ever use the data directly from the form post to hydrate a model object as this completely bypasses any cleaning of data performed by the form classes. Third, the view can be greatly simplified. I’m going to assume you’re using Django 1.7:
# forms.py
from django import forms
from django.contrib.auth.forms import UserCreationForm
from django.contrib.auth.models import User
from .models import Perfil
class UsarioForm(UserCreationForm):
class Meta:
model = User
exclude = ()
class PerfilForm(forms.ModelForm):
class Meta:
model = Perfil
exclude = ('usario',)
# views.py
from django.shortcuts import render
from .forms import UsarioForm, PerfilForm
def nuevo_usario(request):
usario_form = UsarioForm(request.POST or None)
perfil_form = PerfilForm(request.POST or None)
if request.method == 'POST':
if usario_form.is_valid() and perfil_form.is_valid():
usario = usario_form.save()
perfil = perfil_form.save(commit=False)
perfil.usario = usario
perfil.save()
perfil.save_m2m()
return render(request, 'nuevousario.html',
{'usario_form': usario_form, 'perfil_form': perfil_form})
Let the ModelForm classes do what they are designed to do – create objects from sanitized data. You don’t have to do all of that work by hand in the view. You template code also needs some help:
# nuevousario.html
<form action="." method="post" enctype="application/x-www-form-urlencoded">
<table>
<tfoot>
<tr>
<td>
{% csrf_token %}
<button type="submit">Registrar</button>
</td>
</tr>
</tfoot>
<tbody>
{{ usario_form.as_table }}
{{ perfil_form.as_table }}
</tbody>
</table>
</form>
Are you sure you want to use a table for this form? Is it really tabular data? Doesn’t seem very semantically correct. You might consider using an ordered list: <ol>
Hope that helps you out.
0
Taking the comments of @Brandon i have changed my code like this.
I added two URLs, one for the empty form and the other to GET the user data
#urls.py
url(r'^usuarios/$','main.views.usuarios',name='usuarios'),
url(r'^usuarios/(\d+)$','main.views.usuarios',name='editar_usuario'),
In only one view that can handle both URLs, I look for a user_id, if there is Nothing, then I display the empty form, otherwise I get the user and profile data, and with an instance
I put the data into the input fields
#views.py
def usuarios(request,id_usuario=None):
usuarios = User.objects.all()
#Pide información de un usuario - Ask for user Info
if id_usuario is not None:
usr = User.objects.get(pk=id_usuario)
prf = Perfil.objects.get(usuario=usr)
usuario_form = UsuarioForm(instance=usr)
perfil_form = PerfilForm(instance=prf)
#El formulario está vacío para nuevo usuario -Empty User Form
else:
usuario_form = UsuarioForm(request.POST or None)
perfil_form = PerfilForm(request.POST or None)
#Botón Registrar - Register Button pressed
if request.method == 'POST':
#Si está editando se obtiene la instancia del que quiere guardar - If edit, then gets the instance to save
if id_usuario is not None:
usuario_form = UsuarioForm(request.POST, instance=usr)
perfil_form = PerfilForm(request.POST, instance=prf)
#Finalmente guarda - Finally Saves the form
if usuario_form.is_valid() and perfil_form.is_valid():
usuario = usuario_form.save()
perfil = perfil_form.save(commit=False)
perfil.usuario = usuario
perfil.save()
HttpResponseRedirect('/usuarios/')
return render(request,'usuarios.html',locals())
Finally I added some bootstrap/crispy into the form and make it looks better.
#Template usuarios.html
{% block content %}
<div class="row">
<div class="col-md-4">
<h3>Usuarios Registrados</h3>
<ul>
{% for usuario in usuarios %}
<li><a class="usuario_link" href="/usuarios/{{usuario.pk}}">{{ usuario.username }} - {{ usuario.first_name }}</a></li>
{% empty %}
<li>No hay usuarios.</li>
{% endfor %}
</ul>
</div>
<div class="col-md-5">
<fieldset>
<form id="form" method="post" action=''>{% csrf_token %}
{{usuario_form|crispy}}
{{perfil_form|crispy}}
<p><input class="btn btn-default" type="submit" value="Registrar"/></p>
</form>
</fieldset>
</div>
<div class="col-md-2 col-md-offset-1">
<a href="/usuarionuevo/"><input class="btn btn-default" type="button" value="Nuevo Usuario" /></a>
</div>
</div>
{% endblock %}
I hope it helps someone, I am new in python and django so, thanks again @Brandon for the fantastic counseling.
If anyone have a better answer, let me know please.
- [Answer]-Boto error repeatedly appearing on Sentry server
- [Answer]-Django Admin change_list forcing search_form to reject given seach keywords
- [Answer]-Django redirect still allows post on reload only on mobile Chrome
- [Answer]-Filtering two models