Django 1.5 - django-ldap-auth
Trying to figure out how to properly using request_to_context as it only works on the login.html page itself. (user.is_authenticated etc).
After the user gets logged in, it forwards the user to /reboot. From there I want to use {{ user.is_authenticated }} / {{ user.username }}, but nothing shows up(true or false). It is just blank.
On the login.html page itself they work correctly. If I render to the reboot/index.html it does not render the code that I have the index do. I assumed I would be able to call these commands after a user is authenticated. Hopefully I am just missing a small piece to this puzzle.
I have included all of the necessary code. Let me know if you need something else.
Here is my layout.
reboot/form.py
from django import forms
from django.contrib.auth.models import User
from django.forms import ModelForm
class LoginForm(forms.Form):
username = forms.CharField(label=(u'User Name'))
password = forms.CharField(label=(u'Password'), widget=forms.PasswordInput(render_value=False))
views.py
from django.template import Context, loader, RequestContext
from django.shortcuts import render_to_response
from django.contrib.auth.decorators import login_required
from django.contrib.auth import authenticate, login, logout
from django.contrib.auth.models import User
from django.http import HttpResponse, HttpResponseRedirect
from servers.models import Server
from reboot.forms import LoginForm
import paramiko
import socket
def logout_user(request):
logout(request)
return HttpResponseRedirect('/status/')
def index(request):
t = loader.get_template('reboot/index.html')
servers = Server.objects.all()
c = Context( {
'servers': servers,
})
return HttpResponse(t.render(c))
def test_ssh_liveness(ssh, name):
try:
ssh.connect(name, timeout='1')
return True
except socket.timeout:
# server is down
return False
except socket.gaierror:
# invalid server name
return False
except paramiko.SSHException:
# unknown host key
return True
def server(request, name):
ssh = paramiko.SSHClient()
is_alive = test_ssh_liveness(ssh, name)
return HttpResponse("You selected server "+name+" and it is "+str(is_alive))
# user login
def login_user(request):
if request.user.is_authenticated():
# return HttpResponseRedirect('/reboot/')
pass
if request.method == '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)
return HttpResponseRedirect('/reboot/')
else:
return render_to_response('login.html', {'form', form}, context_instance=RequestContext(request))
else:
''' user is not submitting the form, show the login form '''
form = LoginForm()
context = {'form': form}
return render_to_response('login.html', context, context_instance=RequestContext(request))
reboot.urls
from django.conf.urls import patterns, url
from reboot import views
urlpatterns = patterns('',
url(r'^$', views.index, name='index'),
#(r'^$', views.login_user),
url(r'^server/(?P<name>[^/]+)', views.server, name='server')
)
main url file
from django.conf.urls import patterns, include, url
from django.contrib import admin
admin.autodiscover()
urlpatterns = patterns('',
url(r'^admin/doc/', include('django.contrib.admindocs.urls')),
url(r'^admin/', include(admin.site.urls)),
url(r'^reboot/', include('reboot.urls')),
# Login for reboot
(r'^login/$', 'reboot.views.login_user'),
(r'^logout/$', 'reboot.views.logout_user'),
url(r'^status/', include('status.urls')),
)
login.html
% extends "base.html" %}
{% block content %}
<p> print {{ user.is_authenticated }}</p>
<div id="login">
<form class="form-horizontal" name="LoginForm" action="/login/" method="post">
{% csrf_token %}
{% if next %}
<input type="hidden" name="next" value="{{ next }}" />
{% endif %}
<div class="control-group">
<label class="control-label" for="username">Username</label>
<div class="controls">
<input type="text" id="username" name="username" placeholder="Username">
</div>
</div>
<div class="control-group">
<label class="control-label" for="password">Password</label>
<div class="controls">
<input type="password" name="password" id="password" placeholder="Password">
</div>
</div>
<div class="control-group">
<div class=controls">
<button type="submit" class="btn">Login</button>
</div>
</div>
</form>
</div>
{% endblock %}
/reboot/index.html
{% extends "base.html" %}
{% block title %}Server{% endblock %}
{% block content %}
<h2>Server Control Panel</h2>
<h4>Welcome, print {{ user.is_authenticated }}.</h4>
{% if user.is_authenticated %}<p>Logout</p>{% else %}Login</p>{% endif %}
<p class="lead">
The servers below correspond to servers that you have access to.
If you believe there are errors, please contact me.
</p>
<div class="container-fluid">
<table class="table table-hover">
<thead>
<tr>
<th><h4>Hostname</h4></th>
<th><h4>Commands</h4></th>
</tr>
</thead>
<tbody>
{% for server in servers %}
<tr>
<td>{{ server.hostname }}</td>
<td>
start
restart
shutdown
</td>
</tr>
{% endfor %}
</tbody>
</table>
</table>
</div>
{% endblock %}
I appreciate all of your help. I have been stuck on this issue for a few days now and have not been able to figure it out.
John
Your view needs a RequestContext instance (docs), like your login view, so it knows which user is logged in (and other stuff). So instead of:
def index(request):
t = loader.get_template('reboot/index.html')
servers = Server.objects.all()
c = Context( {
'servers': servers,
})
return HttpResponse(t.render(c))
just make it:
def index(request):
servers = Server.objects.all()
context = {
'servers': servers,
}
return render_to_response('reboot/index.html', context, context_instance=RequestContext(request))
EDIT
It's not really about the render_to_response. As the import says, that's just a shortcut.
Django's context processors (basically, functions that add variables to your template context) are request-based, and therefor are only called if you specify a RequestContext, and that includes django.contrib.auth.context_processors.auth, the context processor that includes the user variable into your template.
The equivalent of your code would be:
def index(request):
t = loader.get_template('reboot/index.html')
servers = Server.objects.all()
c = RequestContext(request, {
'servers': servers,
})
return HttpResponse(t.render(c))
Related
I am working on a Django project and I want to fill out a form and save the data in the db database and then be able to show it on another page, I managed to create the form, following some tutorials, but it does not write me anything in the database. Here's how I currently have things:
forms.py
from django import forms
from .models import AusenciasForm
from django.contrib.auth.models import User
class AusenciasForm(forms.ModelForm):
class Meta:
model = AusenciasFormulario
fields = '__all__'
widgets = {'fecha': forms.DateInput(attrs={'type': 'date'})}
models.py
from django.db import models
from django.utils import timezone
import datetime
from django.contrib.auth.models import User
from django.urls import reverse
class AusenciasFormulario(models.Model):
#razon = models.ModelChoiceField(label="Razón", queryset=razones.object.all())
fecha = models.DateField(("Date"),default=datetime.date.today)#label="Fecha", required=True
razon = [
('Estudios/Examen','Estudios/Examen'),
('Enfermedad','Enfermedad'),
('Lesión','Lesión'),
('Motivos personales','Motivos personales'),
('Motivos familiares','Motivos familiares'),
('Otros','Otros')
]
motivo = models.CharField(max_length=100, choices=razon, default='Otros')
comentarios= models.CharField(max_length=200,blank=True)
jugador = User
views.py
class FormularioAusenciaView(HttpRequest):
def index(request):
ausencias_formulario = AuForm.objects.all()
return render(request, 'blog/ausencias.html', {'ausencias_formulario':ausencias_formulario})
def procesar_formulario(request):
#if request.method == 'POST':
form = AusenciasForm(request.POST)
if form.is_valid():
form.save()
form = AusenciasForm()
return HttpResponseRedirect('ausencias/') #Add your route name, where you want to go after form save
else:
form = AusenciasForm()
return render(request, 'blog/formularioAusencia.html', {'form':form})
Urls.py
from django.urls import path
from .views import PostListView, PostDetailView, PostCreateView, PostUpdateView, PostDeleteView,UserPostListView, FormularioAusenciaView, ausencias
from .import views
from django.contrib.auth.decorators import login_required
urlpatterns = [
path('', login_required(PostListView.as_view()), name='blog-home'),
path('user/<str:username>',login_required( UserPostListView.as_view()), name='user-posts'),
path('post/<int:pk>/',login_required( PostDetailView.as_view()), name='post-detail'),
path('post/new/',login_required( PostCreateView.as_view()), name='post-create'),
path('post/<int:pk>/update/',login_required( PostUpdateView.as_view()), name='post-update'),
path('post/<int:pk>/delete/',login_required( PostDeleteView.as_view()), name='post-delete'),
path('about/', views.about, name='blog-about'),
path('formularioAusencia/',login_required( FormularioAusenciaView.index), name='formularioAusencia'),
#path('asistencia_done/',formularioAusencia, name='asistencia_done'),
path('ausencias/',login_required( views.ausencias), name='ausencias'),
]
the template
{% extends "blog/base.html" %}
{% load crispy_forms_tags %}
{% block content %}
<div class="content-section">
<div class="media">
<img class="rounded-circle account-img" src="{{ user.profile.image.url }}">
<div class="media-body">
<h2 class="account-heading">{{ user.username }}</h2>
<p class="text-secondary">{{ user.email }}</p>
</div>
</div>
{% if user.is_authenticated %}
<p></p><a class="mr-2">Rellenar si no vas a poder acudir a un próximo entrenamiento o partido</a></p>
<!--<label><input type="checkbox" id="cbox1" value="first_checkbox"></label><br>-->
<form method="POST" action="{% url 'ausencias' %}">{% csrf_token %}
{{ form|crispy }}
<button class="btn btn-danger btn-sm mt-1 mb-1" type="submit">Enviar</button>
</form>
</div>
<div class="form-group">
</div>
{% endif %}
</div>
{% endblock content %}
In forms.py:
You have imported wrong model name:
change this
from .models import AusenciasForm
To this:
from .models import AusenciasFormulario
And in views.py file:
You have not added any orm query so that's why it is not saving in db.
views.py :
Do this:
def index(request):
ausencias_formulario = AusenciasFormulario.objects.all() #Here i have retrieved data using orm
return render(request, 'blog/formularioAusencia.html', {'ausencias_formulario':ausencias_formulario})
def procesar_formulario(request):
if request.method == 'POST':
form = AusenciasForm()
if form.is_valid():
form.save()
return HttpResponseRedirect('/home/') #Add your route name, where you want to go after form save
else:
form = AusenciasForm()
return render(request, 'blog/formularioAusencia.html', {'form':form})
And in your templates:
formularioAusencia.html
<form method='post'>
{{form}}
<input type="submit" /> #Added new code here
</form>
After submitting above form, using below code, you will get that fields.
Add below code after the form tag.
To display all the fields to templates add the below code in template:
{% for field in ausencias_formulario %}
{{field.fecha}}
#Add remaining fields here to display
{% endfor %}
I need one help. I need to implement the forget password functionality using Django. I am using the Django signup and login page. My code is below:
login.html:
{% extends 'base.html' %}
{% block content %}
<h2>Log in</h2>
{% if form.errors %}
<p style="color: red">Your username and password didn't match. Please try again.</p>
{% endif %}
<form method="post">
{% csrf_token %}
{% for field in form %}
<p>
{{ field.label_tag }}<br>
{{ field }}<br>
{% for error in field.errors %}
<p style="color: red">{{ error }}</p>
{% endfor %}
{% if field.help_text %}
<p><small style="color: grey">{{ field.help_text }}</small></p>
{% endif %}
</p>
{% endfor %}
<button type="submit">Log in</button>
New to My Site? Sign up
</form>
{% endblock %}
views.py:
class Signup(View):
""" this class is used for user signup """
def get(self, request):
""" this function used to get the sign up form """
form = UserCreationForm()
return render(request, 'plant/signup.html', {'form': form})
def post(self, request):
""" this function used for post the sign up data """
form = UserCreationForm(request.POST)
if form.is_valid():
form.save()
return redirect('login')
class AuthLogin(View):
""" Its for login """
def get(self, request):
""" this function used to get the login form """
form = AuthenticationForm()
return render(request, 'plant/login.html', {'form': form})
def post(self, request):
""" this function used for post the login data """
form = AuthenticationForm(None, request.POST or None)
if form.is_valid():
login(request, form.get_user())
return redirect('/')
urls.py:
urlpatterns = [
url(r'^$', TemplateView.as_view(template_name="plant/index.html")),
url(r'^logout/$', auth_views.logout,
{'next_page': 'login'}, name='logout'),
url(r'^login/$', core_views.AuthLogin.as_view(), name='login'),
url(r'^signup/$', core_views.Signup.as_view(), name='signup'),
]
In login page I should have the forget password link. When user will click on it, the reset password page will open and another one condition is after trying 3 wrong attempt the forget password button will be invisible for 1 hour.
Do not create this functionality yourself but use the built-in Django auth views. https://docs.djangoproject.com/en/1.11/topics/auth/default/#built-in-auth-views
The only thing you need to do is add the contrib auth urls to your project:
urlpatterns = [
url('^', include('django.contrib.auth.urls')),
]
This gives you all views like login, logout, password reset etc.
If you want to customise the templates, copy the templates form /path/to/site-packages/django/contrib/admin/templates/registration/ to your app project/app/templates/registration/ and make any customisations
there.
If your app is listed before 'django.contrib.auth' in INSTALLED_APPS (it should always be like that) your custom templates will be picked first.
I am working on a little project on Django, I have had some issues on rendering ModelForm. In main.html tag {{form.ad_p}} doesn't seem working. I only see "Save" button and don't see any ModelForm fields.
If I put below code to shell
form = AddPath()
form.as_p()
I see:
form.as_p()
u'<p><label for="id_name">Name:</label> <input id="id_name" maxlength="200" name="name" type="text" /></p>\n<p><label for="id_route_data">Route data:</label> <textarea cols="40" id="id_route_data" name="route_data" rows="10">\r\n</textarea></p>'
Can you explain, what am I doing wrong?
I already searched on stackoverflow, but same problem hasn't been resolved. I hope, I'll be more lucky
models.py:
from django.db import models
from django.contrib.auth.models import User
class Path(models.Model):
user = models.ForeignKey(User)
name = models.CharField(max_length='200')
route_data = models.TextField()
def __unicode__(self):
return self.name
views.py:
from django.shortcuts import render_to_response
from django.http import HttpResponse
from django.core.context_processors import csrf
from google_maps.forms import AddPath
def index(request):
args = {}
args.update(csrf(request))
form = AddPath()
return render_to_response('main.html', args)
def add_path(request):
#me = request.user
me = 'test'
if request.method == 'POST':
form = AddPath(request.POST)
if form.is_valid():
tmpForm = form.save(commit=False)
tmpForm.user = me
tmpForm.save()
return HttpResponse('Saved')
else:
return HttpResponse(form.errors)
main.html
{% extends 'basis.html' %}
{% block leftbar %}
<form action={% url 'add_path' %} method="post">
{% csrf_token %}
{{ form.as_p }}
<input type="hidden", id="coordinate" name="coordinate"/>
<input type="submit" name="submit" value="Save"/>
</form>
{% endblock %}
I have a login form that I want to be available in all my views, so I created a context processor to add this form to every loaded context.
The problem is that {% csrf_token %} on the form template won't render the hidden input tag with the CSRF token value.
This is the context_processor order in settings.py:
TEMPLATE_CONTEXT_PROCESSORS = (
'django.contrib.auth.context_processors.auth',
'django.core.context_processors.debug',
'django.core.context_processors.i18n',
'django.core.context_processors.media',
'django.core.context_processors.static',
'django.core.context_processors.tz',
'django.contrib.messages.context_processors.messages',
'django.core.context_processors.request',
'django.core.context_processors.csrf',
'absolute.context_processors.absolute',
'myproject.app.context_processors.base',
)
And then the processor itself on app/context_processors.py:
from django.contrib.auth.forms import AuthenticationForm
def base(request):
context = dict()
if not request.user.is_authenticated():
context['login_form'] = AuthenticationForm()
return context
The form template:
{% load i18n %}
<form method="post" action="{% url "django.contrib.auth.views.login" %}">
{% csrf_token %}
<input type="hidden" name="next" value="{% if request.GET.next %}{{ request.GET.next }}{% else %}{{ request.get_full_path }}{% endif %}" />
{{ login_form.as_p }}
<input type="submit" class="button success expand" value="{% trans 'Login' %}" />
</form>
The HTML output for this form:
<form action="/accounts/login/" method="post">
<input type="hidden" value="/" name="next">
<p><label for="id_username">Usuário:</label> <input type="text" name="username" maxlength="254" id="id_username"></p>
<p><label for="id_password">Senha:</label> <input type="password" name="password" id="id_password"></p>
<input type="submit" value="Login" class="button success expand">
</form>
And the error I get when submitting it:
CSRF verification failed. Request aborted.
However, and as I'm only using class-based views, if I add a csrf_protect decorator the form will work, but like this I would have to declare the dispatch method in all my views:
from django.views.decorators.csrf import csrf_protect
class HomeView(TemplateView):
template_name = 'home.html'
#method_decorator(csrf_protect)
def dispatch(self, *args, **kwargs):
return super(HomeView, self).dispatch(*args, **kwargs)
Problem status
I gave up from putting the AuthenticationForm on all my views by creating a login form page. Anyway, it would still be awesome if someone could help me find a solution for this problem.
I've spent a couple of hours fighting an issue similar to the one you've described here. The {% csrf_token %} wasn't rendering anything and I was seeing this when in debug mode:
defaulttags.py:66: UserWarning: A {% csrf_token %} was used in a template, but the context did not provide the value. This is usually caused by not using RequestContext.
I was using a simple view that inherited from a TemplateView:
class MenuIndexView(TemplateView):
template_name = 'menu/index.html'
def get_context_data(self, **kwargs):
kwargs = super().get_context_data(**kwargs)
session = self.request.session
kwargs['zip_code'] = session.get('zip_code')
kwargs['calendar'] = helpers.get_menu_calendar(date.today() + timedelta(days=1), timedelta(days=14))
kwargs['forms'] = {'zip_code': forms.ZipCodeForm({'zip_code': session.get('zip_code')})}
return kwargs
After fussing around a bit under Django's I realized that pretty much no context at all was available where the tag was being generated (CsrfTokeNode on Django's defaulttags.py file):
class CsrfTokenNode(Node):
def render(self, context):
csrf_token = context.get('csrf_token', None)
if csrf_token:
if csrf_token == 'NOTPROVIDED':
return format_html("")
else:
return format_html("<input type='hidden' name='csrfmiddlewaretoken' value='{}' />", csrf_token)
else:
# It's very probable that the token is missing because of
# misconfiguration, so we raise a warning
if settings.DEBUG:
warnings.warn(
"A {% csrf_token %} was used in a template, but the context "
"did not provide the value. This is usually caused by not "
"using RequestContext."
)
return ''
In this point of the code I was only seeing an item within the context, with a zip_code key.
I opened up the main template file and realized that I was making a rookie mistake - this was my main template menu/index.html:
{% extends 'base.html' %}
{% block content %}
<div class="menu-order-meta zip_calendar">
<div class="ink-grid align-center">
<div class="column-group gutters half-vertical-padding medium">
{% include 'partials/menu/zip-code.html' with zip_code=zip_code only %}
</div>
</div>
</div>
{% endblock %}
I was including the form through a partial template and I was explicitly restricting the available context within that partial template - notice the with zip_code=zip_code only declaration - (and by doing so, implicitly turning the csrf_token context processor unavailable).
Maybe are you missing django.middleware.csrf.CsrfViewMiddleware in MIDDLEWARE_CLASSES ?
MIDDLEWARE_CLASSES = (
....
'django.middleware.csrf.CsrfViewMiddleware',
....
)
EDIT: the view now does log me in when I enter a correct username and password, but doesn't return any errors when I enter incorrect username and passwords.
I am using the generic login view provided by Django. This is my login.html template:
<body>
<h1>User Login</h1>
{% if form.has_errors %}
<p>Your username and password did not match.
Please try again.</p>
{% else %}
<form method="post" action=" . ">{% csrf_token %}
<p><label for="id_username">Username:</label>
{{ form.username }}</p>
<p><label for="id_password">Password:</label>
{{ form.password }}</p>
<input type="hidden" name="next" value="/" />
<input type="submit" value="login" />
</form>
{% endif %}
</body>
Now, I am following the tutorial in the book called "Pact Publishing. Learning Website Development with Django". The view never returns
form.has_errors
even though I purposely submit an incorrect username and password. It just keeps returning me to the same page after I click submit. Also, according to the HTML book I read, it said that the 'action' attribute in the form is the URL of the page on the server that will retrieve the information. Is that why it isn't working? Because my
action=" . "
?
EDIT: the view is the generic login view:
#sensitive_post_parameters()
#csrf_protect
#never_cache
def login(request, template_name='registration/login.html',
redirect_field_name=REDIRECT_FIELD_NAME,
authentication_form=AuthenticationForm,
current_app=None, extra_context=None):
"""
Displays the login form and handles the login action.
"""
redirect_to = request.REQUEST.get(redirect_field_name, '')
if request.method == "POST":
form = authentication_form(data=request.POST)
if form.is_valid():
# Ensure the user-originating redirection url is safe.
if not is_safe_url(url=redirect_to, host=request.get_host()):
redirect_to = resolve_url(settings.LOGIN_REDIRECT_URL)
# Okay, security check complete. Log the user in.
auth_login(request, form.get_user())
if request.session.test_cookie_worked():
request.session.delete_test_cookie()
return HttpResponseRedirect(redirect_to)
else:
form = authentication_form(request)
request.session.set_test_cookie()
current_site = get_current_site(request)
context = {
'form': form,
redirect_field_name: redirect_to,
'site': current_site,
'site_name': current_site.name,
}
if extra_context is not None:
context.update(extra_context)
return TemplateResponse(request, template_name, context,
current_app=current_app)
and my urls.py is just
url(r'^$', main_page),
url(r'^user/(\w+)/$', user_page),
url(r'^login/$', login),
Ah, found the answer over here:
form.has_errors tag not working
form.has_errors
was replaced with
form.errors
Try this.
Login.Html
<form action ="." method = POST>
{% csrf_token %}
{{ form.as_p }}
<input type = "submit" value = "login" class="btn">
</form>
urls.py
from django.contrib.auth.views import login, logout
from django.conf.urls import *
urlpatterns = patterns('',
url(r'login/',login,kwargs = {'template_name' : 'templates/auth/login.html'},
url(r'logout', logout,kwargs = {'template_name' : 'templates/auth/logout.html'}),
)
settings.py
LOGIN_REDIRECT_URL = '/dashboard'
LOGIN_URL = '/login/'