How to put login and registration form on same index page - django

As of now, I have my registration form and my log in form on two different pages, I can't seem to put them in one view because the way I did it, the views require different return statements. So here is my registration view function:
def register_user(request):
if request.method == 'POST':
form = MyRegistrationForm(request.POST)
if form.is_valid():
form.save()
return HttpResponseRedirect('/accounts/register_success')
args = {}
args.update(csrf(request))
args['form'] = MyRegistrationForm()
return render_to_response('register.html', args)
def register_success(request):
return render_to_response('register_success.html')
and here is my log in and authentication view:
def login(request):
c = {}
c.update(csrf(request))
return render_to_response('login.html', c)
def auth_view(request):
username = request.POST.get('username', '')
password = request.POST.get('password', '')
user = auth.authenticate(username=username, password=password)
if user is not None:
auth.login(request, user)
return HttpResponseRedirect('/accounts/loggedin')
else:
return HttpResponseRedirect('/accounts/invalid')
Here is the template for the log in page:
<form action="/accounts/auth/" method="post">{% csrf_token %}
<label for="username">User name:</label>
<input type="text" name="username" value="" id="username">
<label for="password">Password:</label>
<input type="password" name="password" value="" id="password">
<input type="submit" value="login" />
</form>
and here is the template for the registration page:
<h2>Register</h2>
<form action="/accounts/register/" method="post">{% csrf_token %}
{{form}}
<input type="submit" value="Register" />
</form>
Again, I can't seem to put them together because the views have to return different things.. any idea on how to do it?
EDIT: This is my urls.py:
url(r'^admin/', include(admin.site.urls)),
url(r'^$', index),
url(r'^accounts/auth/$', auth_view),
url(r'^invalid/$', invalid_login),
url(r'^accounts/register/$', register_user),
url(r'^accounts/register_success/$', register_success),
so it will only use the register_user view if the url is accounts/register, I want it to user the register_view view if it is the homepage (^$). My index view is this:
def index(request):
c = {}
c.update(csrf(request))
return render_to_response('index.html', c)
it basically just adds a csrf token to my index.html (log in template, as seen above). This is why I want to be able to somehow merge index and the register_user view, since register_user view calls the actual form = MyRegistrationForm(request.POST) which is used in the registration template (the registration template uses {{form}}

If you just want to show login and registration on the same page. Create a html page with two forms. Action of one of them to url '/accounts/register/' and another one to '/accounts/auth/'.
for example, change your register.html to:
<html>
<head><body>
<form action="/accounts/auth/" method="post">{% csrf_token %}
<label for="username">User name:</label>
<input type="text" name="username" value="" id="username">
<label for="password">Password:</label>
<input type="password" name="password" value="" id="password">
<input type="submit" value="login" />
</form>
<h2>Register</h2>
<form action="/accounts/register/" method="post">{% csrf_token %}
{{form}}
<input type="submit" value="Register" />
</form>
</body>
</html>
When submit the form, it will go to corresponding view and redirect based on that view.
EDIT:To pass a MyRegistrationForm instance you can update the index view as follows:
def index(request):
c = {}
c.update(csrf(request))
c.update({'form':MyRegistrationForm()})
return render_to_response('index.html', c)
use the login.html as above html code in the answer.

You can do this with a help of little Javascript. Let's create a input field first:
<input type="hidden" name="button-name" id="button-name" value="" />
<input type="submit" name="register-button" id="register-button" onclick="changeValue()" />
function changeValue(){
document.getElementById('button-name').value="register"
}
Now, in your views do this:
button_name = request.POST['button-name']
if button-name=='register':
# Do the registration
# Redirect to another view or template
else:
# Do your login thing
# Redirect where you want

Related

How to get the value of a specific field in a form in Django view function?

I am trying to achieve a load-up process in my system where the user will input the load amount and add it to a user's current load.
How can I get the amount entered in my view function?
Here's my function in my views.py
def LoadWallet(request, pk):
user = get_object_or_404(User, id=request.POST.get('user_id'))
user_wallet = user.wallet
if request.method == 'POST':
form = LoadForm(request.POST)
if form.is_valid():
user_wallet = user_wallet+form.instance.load_amount
User.objects.filter(id=pk).update(wallet=user_wallet)
return HttpResponseRedirect(reverse('user-details', args=[str(pk)]))
and the form in my template file
<form action="{% url 'load-wallet' user.pk %}" method="POST">
{% csrf_token %}
<label for="load_amount">Load amount</label>
<input type="text" class="form-control" id="load_amount" onkeyup="replaceNoneNumeric('load_amount')">
<button type="submit" name="user_id" value="{{ user.id }}" class="btn btn-md btn-success" style="float: right; margin: 10px 5px;">Load</button>
</form>
Right now I tried this but it's returning "name 'LoadForm' is not defined". Should I declare the LoadForm first?
Is there a better way to implement this? Thank you!
You might have an easier time using something like this, than LoadForm:
def LoadWallet(request, pk):
user = get_object_or_404(User, id=request.POST.get('user_id'))
user_wallet = user.wallet
if request.method == "POST":
user_id = request.POST["user_id"]
# Other logic here
return ...
And in template
<form class="load-wallet" action="" method="POST">
{% csrf_token %}
<input type="text" name="user_id" placeholder="What is the user id?">
<button type="submit" class="submit-btn"> Submit </button>
</form>

Security Concerns with Login and Register Django HTML Template and Views.py

Do you have any security concerns with what I've done being implemented in a production web app? Either in the Django HTML Template or my views logic?
I would prefer to have the form in actual html rather than using {{ form }}. Is it ok to allow the user to implement very basic passwords?
views.py is:
from django.shortcuts import render, redirect
from django.contrib.auth import get_user_model
User = get_user_model()
from django.contrib.auth import authenticate, login as auth_login
from django.contrib import auth
from memberships.models import UserMembership
from django.contrib.auth.decorators import login_required
from companies.models import Profile
# Create your views here.
def register(request):
if request.method == "POST":
# User has info and wants an account now!
if request.POST['password1'] == request.POST['password2']:
try:
user = User.objects.get(email=request.POST['email'])
return render(request, 'accounts/register.html', {'error': 'Email has already been taken'})
except User.DoesNotExist:
user = User.objects.create_user(request.POST['email'], password=request.POST['password1'])
auth.login(request, user)
company = Profile()
company.businessperson = request.user
company.first_name = request.POST['firstname']
company.last_name = request.POST['lastname']
company.company_name = request.POST['companyname']
company.phone_number = request.POST['phonenum']
company.save()
return redirect('memberships:payment')
else:
return render(request, 'accounts/register.html', {'error': 'Passwords must match'})
# User wants to enter info
return render(request, 'accounts/register.html')
def login(request):
if request.method == "POST":
user = authenticate(email=request.POST["email"], password=request.POST["password"])
if user is not None:
# Our backend authenticated the credentials
auth_login(request, user)
return redirect('dashboard')
else:
# Backend did not authenticate the credentials
return render(request, 'accounts/login.html', {"error": "Incorrect email and or password"})
else:
return render(request, 'accounts/login.html')
def logout(request):
if request.method == "POST":
auth.logout(request)
return redirect('login')
forms in login.html and register.html:
<!-- login.html -->
<form action="{% url 'login' %}" method="POST">
{% csrf_token %}
<div class="form-group">
<input type="email" name="email" id="exampleInputEmail">
</div>
<div class="form-group">
<input type="password" name="password" id="exampleInputPassword" >
</div>
<input type="submit" value="Login">
</form>
<!-- register.html -->
<form action="{% url 'register' %}" method="POST" >
{% csrf_token %}
<input type="text" name="firstname" id="exampleFirstName" >
<input type="text" name="lastname" id="exampleLastName" >
<input type="text" name="companyname" id="exampleInputCompany" >
<input type="tel" name="phonenum" id="exampleInputPhone" placeholder="Phone Number">
<input type="email" name="email" id="exampleInputEmail" placeholder="Email" required>
<input type="password" name="password1" id="exampleInputPassword" placeholder="Password" required>
<input type="password" name="password2" id="exampleRepeatPassword" placeholder="Repeat Password" required>
<input type="submit" value="Register Account">
</form>

Django add form on every page

In my application i need to add a form in base.html, which I've done. For this i used context_processors, now my problem is everytime i'm trying to post, i'm getting a blank page and this error: Method Not Allowed (POST)
In this form i want just to add a button where it will mark all current users notifications as read.
I know that you can use context_processors like this:
def my_context(request):
data = dict()
if request.user.is_authenticated:
data['notifications'] = Notification.objects.filter(user=request.user, read=False)
data['form'] = NotificationForm()
return data
But instead of adding the form i need these lines:
def my_context(request):
data = dict()
if request.user.is_authenticated:
data['notifications'] = Notification.objects.filter(user=request.user, read=False)
if request.method == 'POST':
if 'read-notifications' in request.POST:
for notification in data['notifications']:
notification.read = True
notification.save()
next = request.POST.get('next', '/')
return redirect(next)
return data
The form in base.html:
<form action="" method="POST">{% csrf_token %}
<input type="hidden" name="next" value="{{ request.path }}">
<button type="submit" class="btn m-btn--square btn-primary" name="read-notifications">Mark as read</button>
</form>
urls.py
url(r'^orders/create/$', views.admin_order_document, name='create_order'),
url(r'^orders/waiting/$', views.OrdersWaitingListView.as_view(), name='order_waiting_list'),
url(r'^orders/unallocated/$', views.OrdersUnallocatedListView.as_view(), name='order_unallocated_list'),
url(r'^orders/working/$', views.OrdersWorkingListView.as_view(), name='order_working_list'),
How can i show this form on every page without getting the above error?
So, I chose a different approach and i ended up with this solution:
base.html
<form action="{% url 'mark_read' %}" method="POST">{% csrf_token %}
<input type="hidden" name="next" value="{{ request.path }}">
<button type="submit" class="btn m-btn--square btn-primary" name="action" value="mark_read">Marchează ca citite</button>
</form>
views.py
#login_required()
def read_notifications(request):
if request.method == 'POST':
if 'action' in request.POST:
notifications = Notification.objects.filter(user=request.user, read=False)
for notification in notifications:
notification.read = True
notification.save()
next = request.POST.get('next', '/')
return redirect(next)
urls.py
url(r'^mark-read/$', views.read_notifications, name='mark_read'),
Basically, the form action will redirect me to the view function, it will do what it has to do and it will redirect me back on the same page.

"next" is not redirecting to expected position

I am making a wallet app so if someone goes to http://127.0.0.1:8000/add_money/ to add money and they are not logged in they will be redirected to the login page with next there after the user logs in it should be redirected back to add_money but it is being redirected to their profile.
//ADD MONEY VIEW
def add_money(request):
if not request.user.is_authenticated():
return render(request, 'registration/login.html', {"next": '/add_money/'})
else:
if request.POST:
username = request.user.username
add_amount = request.POST['amount']
wallet = Wallet.objects.filter(username=username).update(add_money(add_amount))
now = datetime.now()
trans = Transaction(from_name=username, wallet_id=wallet.id, date=now, amount=add_amount)
trans.save()
return render(request, 'user_profile.html', {'user': request.user})
return render(request, 'registration/login.html', {"next": '/add_money/'})
//Login View
def user_login(request):
if 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:
login(request, user)
if request.POST['next']:
return render(request, '/add_money/')
return render(request, 'user_profile.html',{'user': user, 'wallet': user.userprofile.wallet_id})
else:
return render(request, 'registration/login.html', {'error': 'User is not active'})
else:
return render(request, 'registration/login.html', {'error': 'User does not exist'})
else:
return render(request,'registration/login.html')
//login template
{% if next %}
<form action="/login/?next={{next}}" method="post">
<input type="hidden" name="next" value={{ next }}>
{%else%}
<form action="/login/" method="post" >
{% endif %}
USERNAME <input type="text" name="username">
PASSWORD <input type="password" name="password">
<input type="submit">
<input type="hidden" name="next">
{% csrf_token %}
</form>
//add_money template
<form action="user_profile.html" method="post">
Amount:<input type="number" name="amount">
<input type="submit" value="Submit">
<button type="button" name="cancel">Cancel</button>
</form>
I'm not sure it how it even manages to get to the account page since you're using the render tag as a mixture of render and redirect.
return render(request, '/add_money/')
You should return a redirect response back to the next url instead
return HttpResponseRedirect(request.GET['next'])
Also, you're passing the next to the login template, not the url
if not request.user.is_authenticated():
return render(request, 'registration/login.html', {"next": '/add_money/'})
you should redirect to the login page here as well with next as a get parameter
return HttpResponseRedirect('/login/?next={}'.format('/add_money/')
You should also look into using the provided url reversing methods instead of hard coding urls
You also should remove the whole if next in the template and just let the login action be the default for the page
{% if next %}
<form action="/login/?next={{next}}" method="post">
<input type="hidden" name="next" value={{ next }}>
{%else%}
<form action="/login/" method="post" >
{% endif %}
should be
<form method="post" >

#login_decorator not working as expected in Django?

I am using #login_decorator('/login/') in every view. Whenever I tried to access other URL it redirects to the login page. The URL turns like this:
http://127.0.0.1:8000/login/?next=/upload_file/
Now, when I enter correct username, password and click Submit, nothing is happening. I am still on the same page with the same URL.
Here's my form.html:
<form action="/login/" method="post">
{% csrf_token %}
Username: <input type="text" name="username" />
Password: <input type="password" name="password" />
<input type="Submit">
Views.py:
def login_upload(request):
try:
if request.method == 'POST':
usern = request.POST['username']
unames = ''.join(usern)
passwo = request.POST['password']
s = ''.join(passwo)
h = hashlib.sha1(s).hexdigest()
db = MySQLdb.connect(user='root', db='galaxy', passwd='devil', host='localhost')
cursor = db.cursor()
cursor.execute("SELECT id, username, password FROM galaxy_user where username=%s and password=%s", (unames, h))
id, compareu, comparep = zip(*cursor.fetchall())
db.close()
return HttpResponseRedirect('/upload_file/')
except ValueError:
return render_to_response('login.html', context_instance=RequestContext(request))
urls.py:
urlpatterns = patterns('',
url(r'^admin/', include(admin.site.urls)),
url(r'^upload_file/', 'fileupload.views.upload_file'),
url(r'^sync/', 'fileupload.views.sync'),
url(r'^login_upload/', 'fileupload.views.login_upload'),
url(r'^upload_file_form', 'fileupload.views.upload_file_form' ),
url(r'^book_list', 'fileupload.views.book_list'),
url(r'^backend/', 'fileupload.backend.show_files')
)
You need to put "next" value in your form
<form action="/login/" method="post">
{% csrf_token %}
Username: <input type="text" name="username" />
Password: <input type="password" name="password" />
<input type="hidden" name="next" value="{{ next }}" />
<input type="Submit">