this is a very basic and quick question in Django.
So in my views, where I am handling the registration, if a user tries to register
with a username that already exists I want to just give a message, like a span next to the
form, saying, "wrong username".
How do I print that message?
Thank you.
This is my part of code:
def register(request):
if request.method == 'POST':
if User.objects.filter(username = request.POST['username']).exists():
#I want to show next to the username textfield in registration form,
#a span for example that says "Wrong Username"
As suggested in a comment above, you should do it in form's clean method which would make things easier. But if you must do it in a view, here's an example:
if request.method == 'POST':
try:
user_exists = User.objects.get(username=request.POST['username'])
return HttpResponse("Username already taken")
except User.DoesNotExist:
# Username doesn't exist
# Do other validation ...
Then show the response in a span using jQuery, or something else.
To get HTTPResponse message, you have to use ajax instead form submit.
Here i am assuming you are using following like html page code.
<input type="text" name="username" id="username"/> <p id="error"></p>
<input type="button" value="Register" id="register">
Now, You have to make an ajax call on button's click event like:
(i assume that you have knowledge of ajax call.)
$("#register").on('click', function(){
var username=$("#username").val();
$.ajax({
.
.
.
success: fuinction(data){
if(data=="error occured"){
$("error").append("wrong username");
}
}
})
});
and views.py code is like this:
def register(request):
if request.method == 'POST':
if User.objects.filter(username = request.POST['username']).exists():
return HTTPResponse("error occured")
I want to modify an answer from above which can be more easier.... i think :) haha:
def register(request):
alert = {
"username": request.GET.get('username', ''),
}
if request.method == 'POST':
username = request.POST.get('username', '')
if User.objects.filter(username = request.POST['username']).exists():
alert['username'] = "Username already exists"
return render(request, 'interface/signup.html', alert)
and in your html: lets just say -->
<form method="POST"> {% csrf_token %}
<h3>Sign Up</h3>
<label class="label">Username:</label><input type="text" name="username" class="form-control" /><br>
{% if username %}
<div class="alert alert-danger alert-dismissible">
×
{{ username }}
</div>
<br>
{% endif %}
</form>
def register(request):
form = UserCreationForm(request.POST)
if form.is_valid():
else:
# Form is invalid, this includes the user already existing
I know it's 2 years late but none of the answers had it and django has a built in way of solving it.
Related
I have a problem with my login template. I´m not sure, but I think I´m using a custom form since the path is templates/registration/login.html . So, I think it gets replaced to the usual django form. But the input fields of my form dont show up, so I only have the login button and some text underneath it. Similar questions I read couldn´t solve it, so I hope someone can me help here. If you need any code more, please let me know. Thanks in advance.
views.py
def login(response):
if response.method == "POST":
form = LoginForm(response.POST)
if form.is_valid():
username = form.cleaned_data.get("username")
password = form.cleaned_data.get("password")
user = authenticate(username=username, password=password)
auth_login(response,user)
return redirect("home")
else:
form = LoginForm()
return render(response, "registration/login.html",{})
urls.py
from register import views as v
path("", v.login, name="login"),
login.html
{% block content %}
<form method="POST">
{% csrf_token %}
<div class="content">
<h3>{{form.username}}</h3>
<h3>{{form.password}}</h3>
<button type="submit">Login</button>
</div>
</form>
<br>
<p>Don´t have an account yet?</p>
<p>Create one here</p>
{% endblock %}
The render() function takes the request object as its first argument, a template name as its second argument and a dictionary as its optional third argument.
so, you should pass {"form": form} as the third argument to the render function.
I have a scheduling app with Event objects and I'm trying to create a form that will allow the user to update an Event that already exists by the press of the button. However, when the user presses the button it doesn't seem to do anything. It just refreshes the page.
{% for a in availability %}
<form method='POST'>
<li><a class="btn btn-primary" href="{% url 'updateevent' a.id %}" type="submit" role="button">{{a.day}}: {{a.start_time}} - {{a.end_time}}</a></li>
</form>
{% endfor %}
view.py:
def updateevent(request, pk):
if request.method == 'POST':
try:
form = EventForm(data=request.POST, instance=post)
updatedEvent = form.save(commit=False)
updatedEvent.requester_user = request.user
updatedEvent.notes = None
updatedEvent.save()
return redirect('/')
except ValueError:
print(form.errors)
return render(request, 'events/createevent.html', {'form':EventForm(), 'error':'There was an error. Please make sure you entered everything correctly!'})
else:
return redirect('/')
I want the user that presses the button to become the "requester_user", a blank field in my Event object. How can I make this happen?
Anchor tag triggers GET request. You should use <button type="submit"></button> or <input type="submit"> for POST request.
I'm trying to set up a basic "Contact" form for my website, which will basically take in values and then put them into a CSV file. The issue I'm having is that the entries cannot be validated cause they're missing a csrf_token?
Here's the relevant code from my app.py:
#app.route('/contact_end', methods=['POST'])
def handle_contact():
form = ContactForm()
print(form.name.data)
if form.validate_on_submit():
print("yup")
with open('data/messages.csv', 'a') as f:
print("oh shit")
writer = csv.writer(f)
writer.writerow([form.name.data, form.email.data, form.message.data])
print("waddup")
return redirect(url_for('contact_handler.html'), name=form.name.data)
print(form.errors)
return render_template('contact.html', form=form)
It skips over the if statement as it never ends out printing the "yup", and instead it prints out the error:
{'csrf_token': ['The CSRF token is missing.']}
The template that this connects to is:
{% extends "base_template.html" %}
{% block title %}Contact us {% endblock %}
{% block content %}
<p>Feel free to use the contact form below to send us any questions you might have.</p></br>
<form action="/contact_end" method="post">
{{ form.csrf_token }}
<label>Your Name <input type="text" name="name"/></label></br>
<label>Your Email <input type="text" name="email"/></label></br>
<label>Your Name <textarea name="message"></textarea></label></br>
<button type="submit">Send</button>
<button type="reset">Clear</button>
</form>
{% endblock %}
I've tried messing with form.csrf_token and .hidden_tags(), but with no success.
As well, this is the initial part of app.py that brings you to the page in the first place, the one above is the endpoint for the form:
#app.route('/contact')
def contact():
return render_template('contact.html', form=form)
Finally, here's my ContactForm class:
class ContactForm(FlaskForm):
print("yep")
name = StringField('Name', validators=[InputRequired()])
email = EmailField('Email', validators=[InputRequired(), Email()])
message = TextAreaField('Message', validators=[InputRequired()])
I've made sure to set my secret key, as well. Anyone have any idea why this isn't working? Many thanks.
You still need to create the form instance in your contact() function:
#app.route('/contact')
def contact():
form = ContactForm()
return render_template('contact.html', form=form)
I'm coding a login. When I programmed the form by hand I got it working.
The code below works:
views.py
def login_view(request):
if request.method == 'GET':
return render(request, 'app/login.htm')
if request.method == 'POST':
username = request.POST.get('username', '')
password = request.POST.get('password', '')
user = auth.authenticate(username=username, password=password)
if user is None:
return HttpResponseRedirect(reverse('error'))
if not user.is_active:
return HttpResponseRedirect(reverse('error'))
# Correct password, and the user is marked "active"
auth.login(request, user)
# Redirect to a success page.
return HttpResponseRedirect(reverse('home'))
template:
<form method="post" action="{% url 'login' %}">
{% csrf_token %}
<p><label for="id_username">Username:</label> <input id="id_username" type="text" name="username" maxlength="30" /></p>
<p><label for="id_password">Password:</label> <input type="password" name="password" id="id_password" /></p>
<input type="submit" value="Log in" />
<input type="hidden" name="next" value="" />
</form>
Great! But now I want to do the same thing using Django's forms.
The code below is not working because I get is_valid() == False, always.
views.py:
def login_view(request):
if request.method == 'POST':
form = AuthenticationForm(request.POST)
print form.is_valid(), form.errors, type(form.errors)
if form.is_valid():
## some code....
return HttpResponseRedirect(reverse('home'))
else:
return HttpResponseRedirect(reverse('error'))
else:
form = AuthenticationForm()
return render(request, 'app/login.htm', {'form':form})
template:
<form action="{% url 'login' %}" method="post">{% csrf_token %}
{{ form.as_p }}
<input type="submit" value="Submit" />
There are a bunch of people on stackoverflow complaining that they get is_valid always false. I have read all those posts, and as far as I can tell I'm not making any of those mistakes. I found a new mistake to make :-)
EDIT: I added a print in the code. The output when opening the login view and submitting is
[27/Dec/2013 14:01:35] "GET /app/login/ HTTP/1.1" 200 910
False <class 'django.forms.util.ErrorDict'>
[27/Dec/2013 14:01:38] "POST /app/login/ HTTP/1.1" 200 910
and so is_valid() is False, but form.errors is empty.
It turns out that Maxime was right after all (sorry) - you do need the data parameter:
form = AuthenticationForm(data=request.POST)
The reason for that, though, is that AuthenticationForm overwrites the signature of __init__ to expect the request as the first positional parameter. If you explicitly supply data as a kwarg, it will work.
(You should still leave out the else clause that redirects away on error, though: it's best practice to let the form re-render itself with errors in that case.)
Check out form.errors which will help you find out why.
If situation arises, that you don't have an option (I was trying to work with bootstrap modals and it was just not working), I had to do this, or else the modal would always trigger even if the form had not issues (and the is_valid is always False by default)
What I needed:
Show modal when I click a button
if errors, show on the same page, the modal, with the error.
In the modal template:
{% if not brand_form.is_valid and brand_form.errors %}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.5.2/js/bootstrap.min.js"></script>
<script type="text/javascript">
$(window).on('load', (function() {
$('#brandAddModal').modal('show');
}));
</script>
{{ brand_form.non_field_errors }}
{% endif %}
In the view:
def add_brand_form(request):
form = BrandForm()
if request.method == 'POST':
form = BrandForm(data=request.POST)
if form.is_valid():
return HttpResponseRedirect('/home')
else:
return render(request, template_name='home.html', context={'brand_form':form})
return render(request, template_name='modal_add_brand.html', context={'brand_form':form})
I already used the answer to this question, but for some reason I'm not getting a good result.
I'm trying to use the same template for my edit form and my add form. Here's my urls.py:
url(r'^app/student/new/$', 'edit_student', {}, 'student_new'),
url(r'^app/student/edit/(?P<id>\d+)/$', 'edit_student', {}, 'student_edit'),
And my views.py:
def edit_student(request, id=None, template_name='student_edit_template.html'):
if id:
t = "Edit"
student = get_object_or_404(Student, pk=id)
if student.teacher != request.user:
raise HttpResponseForbidden()
else:
t = "Add"
student = Student(teacher=request.user)
if request.POST:
form = StudentForm(request.POST, instance=student)
if form.is_valid():
form.save()
# If the save was successful, redirect to another page
redirect_url = reverse(student_save_success)
return HttpResponseRedirect(redirect_url)
else:
form = StudentForm(instance=student)
return render_to_response(template_name, {
'form': form,
't': t,
}, context_instance=RequestContext(request))
And my forms.py:
class StudentForm(ModelForm):
class Meta:
model = Student
exclude = ('teacher',)
And finally my template student_edit_template.html:
<h1>{{ t }} Student</h1>
<form action="/app/student/edit/{{ student.id }}" method="post"> {% csrf_token %}
{{ form.as_p }}
<input type="submit" value="Submit" />
</form>
For some reason, this is throwing a 404:
Page not found (404)
Request Method: POST
Request URL: http://192.168.1.3:5678/app/student/edit/
I'm probably missing something easy here, but at this point I need another set of eyes on it at the very least.
Thanks in advance!
You're getting the 404 because /student/edit/ requires an id at the tail end otherwise there's no route, and when you're coming from /student/new/ you don't have an id yet. Create a route and view for /student/edit/ and put logic in there to handle the case for when you're creating a record on POST.