Django field extending UserCreationForm not showing up in view - python

What I'm trying to accomplish is to extend UserCreationForm to add an e-mail field for each user when they sign- up. Currently I have a form from UserCreationForm with username and password but no e-mail. I extend it with the forms.py file and implement it in my views.py. But when I run tests and look at the signup page the e-mail field is not found.
views.py:
from django.shortcuts import render, redirect
from django.contrib.auth.forms import UserCreationForm
from django.contrib.auth import login as auth_login
from .forms import SignUpForm
# Create your views here.
def signup(request):
if request.method == 'POST':
form = SignUpForm(request.POST)
if form.is_valid():
user = form.save()
auth_login(request, user)
return redirect('index')
else:
form = SignUpForm()
return render(request, 'signup.html', {'form': form})
forms.py:
from django import forms
from django.contrib.auth.forms import UserCreationForm
from django.contrib.auth.models import User
class SignUpForm(UserCreationForm):
email = forms.CharField(max_length = 254, required = True, widget = forms.EmailInput())
class Meta:
model = User
fields = ('username', 'email', 'password1', 'password2')
form.html:
{% load widget_tweaks %}
{% for field in form %}
<div class="form-group">
{{ field.label_tag }}
{% if form.is_bound %}
{% if field.errors %}
{% render_field field class="form-control is-invalid" %}
{% for error in field.errors %}
<div class="invalid-feedback">
{{ error }}
</div>
{% endfor %}
{% else %}
{% render_field field class="form-control is-valid" %}
{% endif %}
{% else %}
{% render_field field class="form-control" %}
{% endif %}
{% if field.help_text %}
<small class="form-text text-muted">
{{ field.help_text|safe }}
</small>
{% endif %}
</div>
{% endfor %}
Now, when I actually go to the sign in page it only presents Username and password fields. However, when I refresh the page or send an invalid form, the e-mail field shows up when the form reloads. It's confirmed that the field is not showing up on initial load when I run tests and get an assertion error:
AssertionError: 0 != 1 : Found 0 instances of 'type="email"' in response (expected 1)

Related

Invalid block tag on line 24: 'form.as_p', expected 'endblock'. Did you forget to register or load this tag?

I'm a new in Django and trying to do a app but now I'm having this error: "Invalid block tag on line 24: 'form.as_p', expected 'endblock'."
TEMPLATE
{% extends "base.html" %}
{% block title %}
<title>Tarefas</title>
{% endblock title %}
{% block content %}
<div class="content">
{% if messages %}
<div class="container">
<br>
{% for message in messages %}
<div class="alert alert-info" role="alert">
{{message}}
</div>
{% endfor %}
</div>
{% endif %}
<div class="container tasks-box">
<table class="table table-striped">
<form method='POST'>
{% csrf_token %}
{% form.as_p %}
<button type="submit" class="btn btn-secondary btn-sec">Adicionar</button>
</form>
[...]
forms.py
from django.forms import ModelForm
from todolist.models import Tasks
class TaskForm(ModelForm):
class Meta:
model = Tasks
fields = ['task','responsible']
views.py
from django.shortcuts import render, redirect
from django.http import HttpResponse
from todolist.models import Tasks
from todolist.forms import TaskForm
from django.contrib import messages
from django.contrib.auth.decorators import login_required
#login_required
def todolist(request):
if request.method == 'POST':
form = TaskForm(request.POST or None)
if form.is_valid():
instance = form.save(commit=False)
instance.manager = request.user
instance.save()
messages.success(request,("Tarefa adicionada"))
return redirect('todolist')
else:
form = TaskForm
all_tasks = Tasks.objects.filter(manager=request.user)
all_users = Tasks.objects.all()
return render(request,'todolist.html',{ 'form':form,
'all_tasks':all_tasks,
'all_users':all_users})
models.py
from django.db import models
from django.contrib.auth.models import User
from django.contrib.auth import get_user_model
# Create your models here.
User = get_user_model()
class Tasks(models.Model):
manager = models.ForeignKey(User, on_delete=models.CASCADE,default=None, related_name='tasks_manager')
task = models.CharField(max_length=300)
done = models.BooleanField(default=False)
responsible = models.ForeignKey(User, on_delete=models.CASCADE, default=None, related_name='tasks_responsible', blank=True, null=True)
def __str__(self):
return self.task
I tryed don't use {{ form }} tag in template and thats work.
I think the problem is in views, but i can't figure out why.
Someone can help me?
From form rendering options as documented
All you need to do to get your form into a template is to place the form instance into the template context. So if your form is called form in the context, {{ form }} will render its and elements appropriately.
There are other output options though for the / pairs:
{{ form.as_table }} will render them as table cells wrapped in <tr> tags
{{ form.as_p }} will render them wrapped in <p> tags
{{ form.as_ul }} will render them wrapped in <li> tags
So you have a typo error in {% form.as_p %} just replace this with {{ form.as_p }}

Django Model form not rendering

Im trying to create a model form on django but it doesnt want to render even though I mapped it properly and created the path.
models.py
from django.db import models
# Create your models here.
Media_Choices = (
("TV", "TV"),
("Radio", "Radio"),
("Youtube", "Youtube"),
("Podcast", "Podcast"),
)
class Appear(models.Model):
Show = models.CharField(max_length=100)
Media = models.CharField(max_length=30, blank=True, null=True, choices=Media_Choices)
Episode = models.IntegerField()
Date = models.DateField(max_length=100)
Time = models.TimeField(auto_now=False, auto_now_add=False)
Producer = models.CharField(max_length=100)
Producer_Email = models.EmailField(max_length=254)
def __unicode__(self):
return self.Show + ' ' + self.Producer_Email
forms.py
from django import forms
from django.core.exceptions import ValidationError
from django.forms import ModelForm
from .models import Appear
class AppsForm(ModelForm):
class Meta:
model = Appear
fields = '__all__'
def clean_Producer_Email(self):
Producer_Email = self.cleaned_data.get('Producer_Email')
if (Producer_Email == ""):
raise forms.ValidationError('field cannot be left empty')
for instance in Appear.objects.all():
if instance.Producer_Email == Producer_Email:
raise forms.ValidationError('Please fill in correct email')
return Producer_Emailenter
views.py
from django.shortcuts import render
from .forms import AppsForm
# Create your views here.
def AppS(request):
form = AppsForm()
context = {'forms': form}
return render(request, 'AppsForm.html', context)
it refuse to render but it displays the html tag that is in the file but not the fields from the form. this is the html template
AppsForm.html
{% extends 'base.html' %}
{% block content %}
{% load crispy_forms_tags %}
<form action="" method="POST">
{% csrf_token %}
{{ form|crispy }}
<input type="submit" value="submit">
</form>
{% endblock %}
you view is wrong try this
def AppS(request):
if request.method == 'POST':
form = AppsForm(request.POST)
if form.is_valid():
form.save()
return redirect('/')
else:
form = AppsForm()
return render(request, 'AppsForm.html', {'form': form})
and in your html
<form method="POST" class="" action="">
{% csrf_token %}
{{ form|crispy }}
<input type="submit" class="" value="Submit">
</form>
now you are good to go and tell me if you still get error
Based on your AppS() function, where you are passing the form as 'forms' to your AppsForm.html you can render it with crispy_forms like:
AppsForm.html:
{% extends 'your_app/base.html' %}
{% block content %}
{% load crispy_forms_tags %}
<form method="POST" class="" action="">
{% csrf_token %}
{{ forms|crispy }}
<input type="submit" class="" value="Submit">
</form>
{% endblock %}
https://django-crispy-forms.readthedocs.io/en/latest/

How to use Customize Model extends from User Model in Django?

I'm new to Django and I have a problem that makes me quite confused. I have a page when users click to change profile, the corresponding page shows up and lets users update their profile. Here is my model:
from django.db import models
import os
from django.db import models
from django.contrib.auth.models import User
from django.conf import settings
from django.utils import timezone
from django.db.models.signals import post_save
from django.dispatch import receiver
# Create your models here.
class Account(models.Model):
user = models.ForeignKey(User, on_delete="CASCADE")
phone = models.CharField(max_length=18)
room = models.CharField(max_length=8)
dob = models.DateField(default=timezone.datetime.now())
active = models.BooleanField(default=True)
avatar = models.ImageField(upload_to='images/', default=os.path.join(settings.STATIC_ROOT, 'avatar.png'))
def __str__(self):
return self.user.username
Here are my forms:
class UserForm(forms.ModelForm):
first_name = forms.CharField(max_length=100,
widget=forms.TextInput(attrs={'class': 'uk-input', 'placeholder': 'Last Name'}))
last_name = forms.CharField(max_length=100,
widget=forms.TextInput(attrs={'class': 'uk-input', 'placeholder': 'Last Name'}))
class Meta:
model = User
fields = ['first_name', 'last_name', 'email']
class ProfileForm(forms.ModelForm):
class Meta:
model = Account
fields = ['phone', 'room', 'dob', 'active', 'avatar']
And I have my views.py like this:
def show_form(request):
user_basic_info = UserForm(request.POST)
form = ProfileForm(request.POST)
if form.is_valid() and user_basic_info.is_valid():
form.save() and user_basic_info.save()
messages.sucess(request, _('Your profile has been successfully updated'))
redirect('my_account')
else:
UserForm()
ProfileForm()
context = {
'user_basic_info': user_basic_info,
'form': form,
}
return render(request, 'my_account.html', context)
Here is my_account.html template:
{% extends 'base.html' %}
{% block title %}My account{% endblock %}
{% block breadcrumb %}
<li class="breadcrumb-item active">Update your information</li>
{% endblock %}
{% block content %}
<div class="row">
<div class="col-lg-6 col-md-8 col-sm-10">
<form method="post" novalidate>
{% csrf_token %}
{% include 'includes/form.html' %}
<button type="submit" class="btn btn-success">Save changes</button>
</form>
</div>
</div>
{% endblock %}
And forms.html:
{% load widget_tweaks %}
<table>
<div class="form-group">############
{{ user_basic_info }} ############# This displays first_name, last_name and email. Also the problem's here, I want to make 2 forms in one form with a better style like the form below.
</div>############
</table>
{% if form.non_field_errors %}
<div class="alert alert-danger" role="alert">
{% for error in form.non_field_errors %}
<p{% if forloop.last %} class="mb-0"{% endif %}>{{ error }}</p>
{% endfor %}
</div>
{% endif %}
{% for field in form %}
<div class="form-group">
{{ field.label_tag }} {% if form.is_bound %} {% if field.errors %} {% render_field field class="form-control is-invalid" %} {% for error in field.errors %}
<div class="invalid-feedback">
{{ error }}
</div>
{% endfor %} {% else %} {% render_field field class="form-control is-valid" %} {% endif %} {% else %} {% render_field field class="form-control" %} {% endif %} {% if field.help_text %}
<small class="form-text text-muted">
{{ field.help_text|safe }}
</small> {% endif %}
</div>
{% endfor %}
So when users want to change their profile, those fields first_name, last_name, email, phone, room, dob, active, avatar need to be displayed. But the first 3 fields belong to the User model and the rest fields are defined in my Account model. I want when users submit the form, those fields are linked together, e.g Account is an instance of User and that information is properly saved to the database in Account model (I have watched some tutorials but I still cannot properly do it). And when logging to the page, login authentication using User model, but when updating the profile it's Account model and User model, but there is no relationship between them, how can I fix all of those errors, thanks in advance.
you need to use OneToOne Relationship here since each user has only one and unique profile details. so in your models.py use :-
user = models.OneToOneField(User, on_delete=models.CASCADE)
If you use default user there is 4 way to extends it so here i give a link follow them,
if you use default user you need to use Usercreation form for Register because the user model have password encryption algorithmuse so when you use you user define form it will not store your password
follow instruction for extends user abstract base model
extends user using
registration form using usercreation form
Define view of save data
follow instruction for extends user using one to one
Create new model Profile and give one to one relationship
Create registration form usring model.formplus additional fields you want to take from user define in form class explicity
in view save form and add user reference in Profile model using create method
link:
extend user model
if you use usercreation form
go through i give link if you got error let me know

Python/Django: How to display error messages on invalid login?

I'm trying to do the Login for my Django (2.0) website, so far I've got the login working for existing accounts. I'm using the built-in login function.
Now I want to display an error message when you enter an invalid account, for example "Invalid username or password!". But I have no idea how to go about this.
Right now it just refreshes the login page when your enter an invalid account. Any help is appreciated!
Login.html
{% block title %}Login{% endblock %}
{% block content %}
<h2>Login</h2>
<form method="post">
{% csrf_token %}
{{ form.as_p }}
<button type="submit">Login</button>
</form>
{% endblock %}
Login view
def login(request):
if request.method == 'POST':
form = AuthenticationForm(request.POST)
username = request.POST['username']
password = request.POST['password']
user = authenticate(username=username, password=password)
if user is not None:
if user.is_active:
auth_login(request, user)
return redirect('index')
else:
form = AuthenticationForm()
return render(request, 'todo/login.html', {'form': form})
in your template
{% for message in messages %}
<div class="alert alert-success">
<a class="close" href="#" data-dismiss="alert">×</a>
{{ message }}
</div>
{% endfor %}
in view
from django.contrib import messages
def login(request):
if request.method == 'POST':
form = AuthenticationForm(request.POST)
username = request.POST['username']
password = request.POST['password']
user = authenticate(username=username, password=password)
if user is not None:
if user.is_active:
auth_login(request, user)
return redirect('index')
else:
messages.error(request,'username or password not correct')
return redirect('login')
else:
form = AuthenticationForm()
return render(request, 'todo/login.html', {'form': form})
You should just add inside your template:
{% block title %}Login{% endblock %}
{% block content %}
<h2>Login</h2>
{% if form.errors %}
<p>username or password not correct</p>
{% endif %}
<form method="post">
{% csrf_token %}
{{ form.as_p }}
<button type="submit">Login</button>
</form>
{% endblock %}
Updating for Django 2.0:
For individual field errors (e.g) :
<input type="text" class="form-control my-4" id="id_username" placeholder="Username" name="username">
{% for error in form.username.errors %}
<p class="text-danger">{{ error }}</p>
{% endfor %}
For non field errors (e.g if password is incorrect):
{% if form.non_field_errors %}
{% for error in form.non_field_errors %}
<p class="text-danger">{{ error }}</p>
{% endfor %}
{% endif %}
You should place the above at the end of all fields.
You already have {{ form.as_p }} in your template, so Django will show any form errors.
The problem is that the AuthenticationForm takes request as its first argument. You can then use form.is_valid() to check whether the username and password are valid and that the user is active, instead of fetching the data from request.POST manually.
def login(request):
if request.method == 'POST':
form = AuthenticationForm(request, request.POST)
if form.is_valid():
auth_login(self.request, form.get_user())
return redirect('index')
else:
form = AuthenticationForm(request)
return render(request, 'todo/login.html', {'form': form})
Another option would be to use the built-in LoginView instead of writing your own:
from django.contrib.auth import views as auth_views
urlpatterns = [
...
path('accounts/login/', auth_views.LoginView.as_view(template_name='todo/login.html')),
...
]
Then set LOGIN_REDIRECT_URL in your settings.
LOGIN_REDIRECT_URL = 'index'

how to put a login form using django

After hours and hours of trying, i still cannot seem to make it happen.
basically Im trying to put a login form inside this .post_list.html using django along with the postform. (so there are 2 forms)
this is the views.py
from django.contrib import messages
from django.http import HttpResponse, HttpResponseRedirect
from django.shortcuts import render, get_object_or_404, redirect
from django.contrib.auth import authenticate, login
from django.contrib.auth import login
from django.http import HttpResponseRedirect
from django.template.response import TemplateResponse
from django.contrib.auth.decorators import login_required
from .forms import PostForm, AuthenticationForm
from .models import Post
def post_detail(request, id=None):
# instance = Post.objects.get(id=1)
instance = get_object_or_404(Post, id=id)
context = {
"title": instance.title,
"instance": instance,
}
return render(request, "post_detail.html", context)
def post_list(request):
if request.method == "POST":
form = AuthenticationForm(request, data=request.POST)
if form.is_valid():
login(request, form.get_user())
return HttpResponseRedirect('/post-list/')
else:
form = AuthenticationForm(request)
return TemplateResponse(request, 'login.html', {'form': form})
else:
form = AuthenticationForm()
postform = PostForm(request.POST or None)
if postform.is_valid():
instance = postform.save(commit=False)
print (postform.cleaned_data.get("title"))
instance.save()
# message success
messages.success(request, "Successfully Created")
return HttpResponseRedirect(instance.get())
# else:
#messages.error(request, "Not Successfully Created")
queryset = Post.objects.all()#.order_by("-timestamp")
context = {
"object_list": queryset,
"title": "List",
"form": postform,
"form2": form
}
return render(request, "post_list.html", context)
and this is the forms.py
from django import forms
from .models import Post
class PostForm(forms.ModelForm):
class Meta:
model = Post
fields = [
"title",
"content"
]
from django.contrib.auth import authenticate
class AuthenticationForm(forms.Form):
username = forms.CharField(max_length=254)
password = forms.CharField(widget=forms.PasswordInput)
def clean(self):
username = self.cleaned_data['username']
password = self.cleaned_data['password']
user = authenticate(username=username, password=password)
if user is None:
raise forms.ValidationError('invalid_login')
return self.cleaned_data
and post_lost.html
{% extends "base.html" %}
{% block content %}
<form method="post" action="">
{% csrf_token %}
Username: {{ form.username }} {{ form.username.errors }}<br>
Password: {{ form.password }} {{ form.password.errors }}<br>
{{ form.errors }}<br>
<input type="submit" value="login" />
</form>
<div class='two columns right mgr'>
<h1>Form</h1>
<form method='POST' action=''>{% csrf_token %}
{{ form.as_p }}
<input class="button-primary" type='submit' value='Create Post' />
</form>
</div>
<div class='four columns left'>
<h1>{{ title }}</h1>
{% for obj in object_list %}
<div class="row">
<div>
<a href='{{ obj.get_absolute_url }}'>
<div class="thumbnail">
<!--<img src="..." alt="...">!-->
<div class="caption">
<h3>{{ obj.title }}<small> {{ obj.timestamp|timesince }} ago</small></h3>
<p>{{ obj.content|linebreaks|truncatechars:120 }}</p>
<!-- <p>View </p>-->
</div>
</div></a>
</div>
<hr />
</div>
{% endfor %}
</div>
{% endblock content %}
could you please help me out? thanks.
My guess is you got this issue because of naming.
You passing into context the following things:
form = AuthenticationForm()
postform = PostForm(request.POST or None)
...
context = {
"object_list": queryset,
"title": "List",
"form": postform,
"form2": form
}
So, when you try to access form.username you fail, because in the template form is a postform. And postform has no 'usarname' field.
So look like you should try this:
<form method="post" action="">
{% csrf_token %}
Username: {{ form2.username }} {{ form2.username.errors }}<br>
Password: {{ form2.password }} {{ form2.password.errors }}<br>
{{ form2.errors }}<br>
<input type="submit" value="login" />
</form>

Categories