Django Template Not Receiving Context Object - python

I'm trying to implement a simple sign up form and slightly tearing my hair out. For some reason, the view doesn't seem to be properly passing the context object I pass it (regardless of what it is.)
here's my code:
urls.py
path(r"signup/", client_views.signup_view, name="page-signup")
views.py
def signup_view(request):
if request.method == 'POST':
form = SignUpForm(request.POST)
if form.is_valid():
form.save()
username = form.cleaned_data.get('username')
raw_password = form.cleaned_data.get('password1')
user = authenticate(username=username, password=raw_password)
login(request, user)
return redirect('page-index')
else:
form = SignUpForm()
context = {'form': form}
return render(request, 'registration/signup.html', context=context)
registration/signup.html
{% extends "base.html" %}
{% load static %}
{% block header %}
Sign Up
{% endblock %}
{% block content %}
<form method="post">
{% csrf_token %}
{{ form.as_p }}
<button type="submit">Sign Up</button>
</form>
{% endblock %}
forms.py
class SignUpForm(UserCreationForm):
first_name = forms.CharField(max_length=30, required=False, help_text='Optional.')
last_name = forms.CharField(max_length=30, required=False, help_text='Optional.')
email = forms.EmailField(max_length=254, help_text='Required. Inform a valid email address.')
class Meta:
model = User
fields = ('first_name', 'last_name', 'email', 'password1', 'password2', )
I've confirmed it's
generating the form properly as html
it's also definitely rendering the correct template
doesn't pass any context even if it's just a string or something
doesn't work with any forms
doesn't work in other templates, implying to me it's in the view
I'm sure this is some stupid mistake but I've been tearing my hair out over this - any help would be greatly appreciated!

It was because my template tags didn't match up
Specifically, I wrote:
{% bloc content %}
instead of
{% block body %}

Related

Why is my Django form not "valid"? Can't get the POST request to update database

I am trying to create a user profiles for users in my Django app. I have the form displaying where I want it to and when I try to submit, nothing happens.
I put a print statement after the form.is_valid in my view.py and found that it wasn't 'valid' but I have no idea why.
I have tried several different ways to 'clean' / 'validate' data but I can't get past the form being 'invalid.'
Any help would be greatly appreciated!
urls:
path('userinfo/', views.user_info, name='userinfo')
form template:
{% extends "base.html" %}
{% load bootstrap4 %}
{% block content %}
<div class="container">
<h1>Enter User Info</h1>
<form method="POST" class="form">
{% csrf_token %}
{% bootstrap_form form %}
<input type="submit" class="btn btn-primary" value="Create Profile">
</form>
</div>
{% endblock %}
view:
def user_info(request):
form = ProfileForm()
if request.method == 'POST':
form = ProfileForm(request.POST)
if form.is_valid():
form.save()
else:
form = ProfileForm()
return render(request, 'miraDashboard/form.html', context={'form': form})
model:
from django.db import models
from django.contrib.auth.models import User
class Profile(models.Model):
user = models.OneToOneField(User,on_delete=models.CASCADE)
name = models.CharField("Full Name", max_length=1024)
job_role = models.CharField("Role", max_length=254, default="Seeking Job Opportunities")
zip_code = models.CharField("Zip Code", max_length=5)
user_image = models.ImageField("Upload Profile Picture", upload_to='images/')
def __str__(self):
return f'{self.user.username} Profile'
form:
from django.forms import ModelForm
from .models import Profile
class ProfileForm(ModelForm):
class Meta:
model = Profile
fields = ['name','job_role','zip_code', 'user_image']
if you want to see errors in form change else statmant:
def user_info(request):
form = ProfileForm()
if request.method == 'POST':
form = ProfileForm(request.POST)
if form.is_valid():
form.save()
else:
print(form.errors.as_data()) # here you print errors to terminal
return render(request, 'miraDashboard/form.html', context={'form': form})
after form.is_valid() you don't need to set it again (form = ProfileForm() in else statment). this way your form will get errors( you cen see them in form.errors).

Django User Profile doesn't update

I am setting up a website in Django, where users can see their profiles and update details (like email, password, etc) or delete own account. But updating the form is not acknowledged at all by the user. I am using the standard built-in User model.
forms.py:
class UserDetailsForm(forms.ModelForm):
password = forms.CharField(widget = forms.PasswordInput())
class Meta:
model = User
fields = ('first_name','last_name','email','password','is_active')
views.py:
#login_required
def edit_profile(request):
user = User.objects.get(username=request.user)
form = UserDetailsForm(request.POST or None,
initial={'first_name':user.first_name,
'last_name':user.last_name,
'email':user.email,
'password':user.password,
'is_active':user.is_active,})
if request.method == 'POST':
if form.is_valid():
user.save()
messages.info(request, 'This is a debug message')
return HttpResponseRedirect(reverse('account'))
context = {"form": form}
return render(request, "iFood/user-account.html", context)
user-profile.html:
...
<form method="POST" action="{% url 'account' %}" class="" enctype="multipart/form-data">
{% csrf_token %}
{{form.as_p}}
<input type="submit" name="" value="Edit and Save">
{% if messages %}
<ul class="messages">
{% for message in messages %}
<li class="{{ message.tags }}">
{{ message }}
</li>
{% endfor %}
</ul>
{% endif %}
First of all you can't change a password like that. You should take the password that user entered and set it with user_obj.set_password():
Django docs: Change password
And for your form:
You doing it wrong with user.save(). There is nothing to save for user object. You should save the form using form.save().
Also request.user is the actual user object not the username.
forms.py:
class UserDetailsForm(forms.ModelForm):
password = forms.CharField(widget = forms.PasswordInput())
class Meta:
model = User
fields = ('first_name','last_name','email'','is_active')
views.py:
#login_required
def edit_profile(request):
user = request.user
form = UserDetailsForm(request.POST or None, instance=user)
if request.method == 'POST':
if form.is_valid():
# Save the changes but password
form.save()
# Change password
new_password = form.cleaned_data.get('password')
if new_password:
user.set_password(new_pass)
messages.info(request, 'This is a debug message')
return HttpResponseRedirect(reverse('account'))
context = {"form": form}
return render(request, "iFood/user-account.html", context)

Why does my own login view with my own User model in Django doesn't work?

I have created my own user model in Django:
class User(AbstractBaseUser, PermissionsMixin):
email = models.EmailField(_('email address'), unique=True)
is_active = models.BooleanField(_('active'), default=False)
token_num = models.IntegerField(_('token count'), default=0)
money_num = models.IntegerField(_('money count'), default=0)
objects = UserManager()
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = []
class Meta:
verbose_name = _('user')
verbose_name_plural = _('users')
So then i decided to do my own login view. Here it is:
def login(request):
if request.method == "POST":
form = LoginForm(request.POST)
email = request.POST.get('email')
password = request.POST.get('password')
user = authenticate(username=email, password=password)
if user is not None and user.is_active:
login(request, user)
return HttpResponseRedirect("/main/")
else:
form = LoginForm()
return render(request, 'registration/login.html', {'form': form})
Here is my LoginForm:
class LoginForm(forms.Form):
user_email = forms.EmailField(max_length=255)
password = forms.CharField(max_length=255)
class Meta:
model = User
fields = ('email', 'password')
And my login.html:
{% extends 'base.html' %}
{% block title %}Login{% endblock %}
{% block content %}
<h2>Login</h2>
<form method="post">
{% csrf_token %}
{% for field in form %}
<p>
{{ field.label_tag }}<br>
{{ field }}
{% if field.help_text %}
<small style="display: none">{{ field.help_text }}</small>
{% endif %}
{% for error in field.errors %}
<p style="color:red">{{ error }}</p>
{% endfor %}
</p>
{% endfor %}
<button type="submit">Login</button>
</form>
{% endblock %}
And here is my urls.py:
urlpatterns = [
url(r'^log/$', views.login)
]
So the problem is that when I enter all data at login page the user doesn't log in and I'm not redirected to the main page. The login page is reloading and that's all.
P.S I have already created 1 user with email and password. This user is_active is set to True (1)
I think that the problem is in your LoginForm.
It is not ModelForm, so you can remove the Meta class.
And your email field is called user_email but in the login view, you try to get email from the POST params.
Try to get the consistent name and you should be able to log in.
Your LoginForm has the field user_email but your code access email from request.POST; these need to be the same.
Note, you should probably check form.is_valid() and get the data from form.cleaned_data, rather than direct from the POST. Also note, your form is (correctly) not a ModelForm so the inner Meta class and its contents are irrelevant.

Add placeholder field to basic UserCreation Django sign up form

I am fairly new to Django and I have set up a sign up form with some additional fields.
In my forms.py file I have the following code:
class SignUpForm(UserCreationForm):
first_name = forms.CharField(max_length=30, required=False, help_text='Optional.')
last_name = forms.CharField(max_length=30, required=False, help_text='Optional.')
email = forms.EmailField(max_length=254, help_text='Required. Inform a valid email address.')
class Meta:
model = User
fields = ('username', 'first_name', 'last_name', 'email', 'password1', 'password2', )
In my views.py I have the following code:
def signup(request):
if request.method == 'POST':
form = SignUpForm(request.POST)
if form.is_valid():
form.save()
username = form.cleaned_data.get('username')
raw_password = form.cleaned_data.get('password1')
user = authenticate(username=username, password=raw_password)
login(request, user)
return redirect('index')
else:
form = SignUpForm()
return render(request, 'signup.html', {'form': form})
Then in my signup.html view I am rendering the following:
<form method="post">
{% csrf_token %}
{% for field in form %}
<p>
{{ field.label_tag }}<br>
{{ field }}
{% for error in field.errors %}
<p style="color: red">{{ error }}</p>
{% endfor %}
</p>
{% endfor %}
<button class="btn-contact" type="submit">Let's Go!</button>
</form>
Essentially what I want to do is add placeholder text in each field but this is not appearing the way I have set it up.
To do this I need more control over the forms fields but I don't know how to do that because of the way I am rendering fields in a loop.
How would I go about doing this?
For placeholders, take a look at How do I add a placeholder on a CharField in Django?
One good advice that I have to give you, is that you shouldn't manually render your form, because Django has mechanisms to do that quite well (like {{form.as_p}} in your case). See Working with forms.

Extending User and UserCreationForm

I need your help.
I extending class User and add same field, than extending UserCreationForm, but form is not valid.
Code crash in if form.is_valid().
Please help, why my form is not correctly?
models.py
class UserProfile(models.Model):
user = models.ForeignKey(User, unique=True, related_name='profile')
nick_name = models.CharField(max_length=15)
My register form
forms.py
class MyRegisterForm(UserCreationForm):
print "OK!"
nick_name = forms.CharField(max_length=30, required=True, widget=forms.TextInput)
print "Ook"
class Meta:
model = UserProfile
def save(self, commit=True):
if not commit:
raise NotImplementedError("Can't create User and UserProfile without database save")
print "Saving..."
user = super(MyRegisterForm, self).save(commit=False)
user.nick_name = self.cleaned_data["nick_name"]
user_profile = UserProfile(user=user, nick_name=self.cleaned_data['nick_name'])
user_profile.save()
print "Saving complete"
return user, user_profile
Register function
views.py
def reg(request):
if request.method =='POST':
form = MyRegisterForm(request.POST)
if form.is_valid():
username = form.cleaned_data['username']
print username
password1 = form.cleaned_data['password1']
print password1
password2 = form.cleaned_data['password2']
print password2
nick_name = form.cleaned_data['nick_name']
print nick_name
form.clean_username()
if password1 == password2:
new_user = form.save()
return render_to_response('registration/registration_complete.html')
else:
print "Password error"
return render_to_response('registration/registration_fail.html')
else:
print "FORM error" #ТУТ ВАЛИТСЯ :(
return render_to_response('registration/registration_fail.html')
else:
form = UserCreationForm() # An unbound form
return render_to_response('registration/registration_new_user.html', {
'form': form,
},context_instance=RequestContext(request))
In setting
settings.py
AUTH_PROFILE_MODULE = 'registration.UserProfile'
Registration template
registration_new_user.html
{% extends "base.html" %}
{% block content %}
<h1>Registration</h1>
<form action="registration" method="post">
{% if form.error_dict %}
<p class="error">Please fix the error.</p>
{% endif %}
{% if form.username.errors %}
{{ form.username.html_error_list }}
{% endif %}
<label for="id_username">Login:</label><br> {{ form.username }}<br>
{% if form.password1.errors %}
{{ form.password1.html_error_list }}
{% endif %}
<label for="id_password1">pass:</label><br> {{ form.password1 }}<br>
{% if form.password2.errors %}
{{ form.password2.html_error_list }}
{% endif %}
<label for="id_password2">pass(again):</label><br> {{ form.password2 }}<br>
{% if form.nick_name.errors %}
{{ form.nick_name.html_error_list }}
{% endif %}
<label for="id_nick_name">nick:</label><br> {{ form.nick_name }}<br>
<br>
<input type="submit" value="Reg" />
</form>
{% endblock %}
Well, you have several issues in your code. For instance, you override UserCreationForm with MyRegistrationForm and indeed you instantiate the latter when the request is a POST, but when is not, you pass the template a normal UserCreationForm.
You do have a user in your UserCreationForm because this is a ModelForm whose model is UserProfile and there you have defined a user field. So it makes perfect sense that the forms complaint about this when you create it with the POST.
I don't see a very clear solution here because your code is somewhat tricky but first of all, use the same form with both GET and POST request type so this line in your views
form = UserCreationForm() # An unbound form
Would change for this one:
form = MyRegistrationForm() # An unbound form
In the template it won't appear the field user because you don't include them but it is in the form. As you are creating a new user, that field should be set to non-required because no user will be associated with the UserProfile because you are creating the user. You can set it to non-required adding the parameter blank=True to the model:
class UserProfile(models.Model):
user = models.ForeignKey(User, unique=True, related_name='profile', blank=True)
nick_name = models.CharField(max_length=15)
UPDATE:
This is the code for your base class UserCreationForm save method:
def save(self, commit=True):
user = super(UserCreationForm, self).save(commit=False)
user.set_password(self.cleaned_data["password1"])
if commit:
user.save()
return user
As you can see, this code assumes that the user has a set_password attribute, in order to fix this, you have to add a def set_password(self, raw_password) method to your UserProfile class. This error happens because the form base class is designed to be used with normal Django User class, any other error you may encounter like this you will probably solve it by adding the fields required to your UserProfile. This one solves like this:
class UserProfile:
...
def set_password(self, raw_password):
# whatever logic you need to set the password for your user or maybe
self.user.set_password(raw_password)
...
I hope this bring some light to the problem. Good luck!

Categories

Resources