How can I use my own template with Django auth_views? - python

I am creating the option for users to change their passwords, and for this I am using Django auth_views, specifically PasswordChangeView (CBV). Django auth_views by default use the Django admin design template. How can I use my own template with only the form of auth_views?
What I tried:
I'm trying to set a template_name. But the auth_views form won't appear...
Only the template I provide will load.
urls.py
from django.contrib.auth import views as auth_views
urlpatterns = [
path('change-password/', auth_views.PasswordChangeView.as_view(template_name='settings/alterar_passwor
d.html'), name="change-password"),
]
Template
alterar_password.html
{% extends 'settings/settings.html' %}
{% load staticfiles %}
{% block settings %}
Mudar a minha password
{% endblock %}
What I expect:
I'm looking forward to use the form provided from auth_views, with the my own template, so I can avoid Django admin design for users.

You could use this or similiar code in your template. Your view will pass standard "form" in your custom template and you have to render it there.
an example:
<form method="post" >
<fieldset>
<legend>Password change</legend>
{% csrf_token %}
{{form.as_p}}
<button type="submit" class="form-button ">Submit</button>
<button type="reset" class="form-button btn ">Reset</button>
</fieldset>
</form>

Related

I keep getting : Reverse for 'delete_entry' with arguments '('',)' not found. 1 pattern(s) tried: ['deleteentry/(?P<input_id>[^/]+)/\\Z']

I am a begginer and tried to look up solutions from other threads to no avail,
Here is my views.py :
#login_required(login_url='/login')
def delete_entry(request, input_id):
input=Diary.objects.get(pk=input_id)
input.delete()
return redirect('home')
Here is my urls.py :
urlpatterns = [
path('', views.welcome, name='welcome'),
path('home', views.home, name='home'),
path('MyEntries/', views.MyEntries, name='entries'),
path('deleteentry/<input_id>/', views.delete_entry, name='delete_entry'),
]
Here is my html code :
<p>Hello, {{user.username}} !</p>
{% for article in articles %}
<p> {{ article.title}}<br>
{{ article.description }} <br>
{{ article.date }}
<div class="card-footer text-muted">
</p>
Delete
</div>
{% endfor %}
{% endblock %}
As the error says, this is because input.id resolves to the empty string, so likely input does not exists, or it has no id.
Likely you should work with article.id, or perhaps even more robust, use article.pk. If you delete items, you need to make a DELETE or POST request, so you can not work with a link, you use a mini-form, so:
<form action="post" method="{% url 'delete_entry' article.pk %}">
{% csrf_token %}
<button type="submit" class="delete">Delete</button>
</form>
The view can be further improved by using get_object_or_404, and restrict the view to only POST and DELETE requests:
from django.shortcuts import get_object_or_404
from django.views.decorators.http import require_http_methods
#login_required(login_url='/login')
#require_http_methods(["DELETE", "POST"])
def delete_entry(request, input_id):
input = get_object_or_404(Diary, pk=input_id)
input.delete()
return redirect('home')

Django Admin Login Form

How do I change the login form used by django admin (want to add a captcha field)? I am using the cookiecutter template and have followed the suggestions in other SO answers, and guides:
forms.py
class AuthAdminForm(AuthenticationForm):
captcha = ReCaptchaField(widget=ReCaptchaV3)
show_something_different = forms.TextInput()
class Meta(AuthenticationForm):
fields = ('email', 'password', 'show_something_different', 'captcha')
urls.py
from django.contrib import admin
from myapp.forms import AuthAdminForm
admin.autodiscover()
admin.site.login_form = AuthAdminForm
admin.site.login_template = 'admin/login.html'
urlpatterns = [
# Django Admin, use {% url 'admin:index' %}
path(settings.ADMIN_URL, admin.site.urls),
...]
I was able to add admin/login.html to my templates dir and extend it. This works to add the google js to the header (can see it in source). But the captcha field and my dummy extra field don't show up.
I was on the right track, but what caught me out is that the login.html template doesn't render every field present in the form (this is why my dummy test field never showed up). So instead of extending login.html, I copied the entire contents to my own file in templates/admin/login.html, then added the captcha field manually:
<form action="{{ app_path }}" method="post" id="login-form">{% csrf_token %}
<div class="form-row">
{{ form.captcha }}
{{ form.username.errors }}
{{ form.username.label_tag }} {{ form.username }}
</div>
base.html can be extended like this:
{% block extrahead %}
<script async src="https://www.googletagmanager.com/gtag/js?id=G-xxx"></script>
<script>
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
gtag('config', 'G-xxx');
</script>
{% endblock %}
Now, finally, captcha is on my admin login page.

How does user variable pass to home view template

I currently following a tutorial at https://wsvincent.com/django-allauth-tutorial-custom-user-model/
I look at how they implemented home view.
pages/views.py
# pages/views.py
from django.views.generic import TemplateView
class HomePageView(TemplateView):
template_name = 'home.html'
templates/home.html
<!-- templates/home.html -->
<h1>Django Login Mega-Tutorial</h1>
{% if user.is_authenticated %}
<p>Hi {{ user.username }}
<p>Log out</p>
{% else %}
<p>Sign Up</p>
<p>Log In </p>
{% endif %}
However, I don't see how user variable is being passed to the home view template (templates/home.html). May I know how that happen?
Assuming you have the default template CONTEXT_PROCESSORS in your settings module, one of which includes django.contrib.auth.context_processors.auth which sets the user variable in all of your templates.
Also, you can look at the source code.

Django Model form don't update database records

I am new in django and I want to create a form to update some database entries.
this is a simple form where I have a simple input text where I write the id of the record that I want to update:
main.html
<form method='post' action='/config/{{ idprov }}' >
<input type="text" class="form-control" name="idprov" id="idprov" value ="{{ idprov }}" />
<input class="btn btn-danger" type="submit" value="Config">
</form>
forms.py
from django import forms
from .models import Proveedor, Estado, Config
class ConfigForm(forms.ModelForm):
class Meta:
model = Config
this is my views.py:
def configView(request,idprov):
prov = Config.objects.get(idproveedor=idprov)
if request.method == 'POST':
form = ConfigForm(request.POST or None, instance=prov)
if form.is_valid():
form.save(commit=false)
return HttpResponseRedirect('/monitor/')
else:
form = ConfigForm( instance=prov)
return render_to_response('config.html',
{'form':form})
my template config.html:
{% extends 'base.html' %}
{% block content %}
<div class="container">
<div class="row">
<div class="col-md-4">
<form method='POST' action='' >
<div class="form-group">{% csrf_token %}
{{ form.as_p }}
</div>
<button type='submit' class="btn btn-primary">Grabar</button>
</form>
</div>
</div>
</div>
{% endblock %}
my urls.py:
from django.conf.urls import patterns, include, url
from prov.views import home
from prov.views import proveedores
from prov.views import estado
from prov.views import monitorViewV2
from django.contrib import admin
admin.autodiscover()
urlpatterns = patterns('',
# Examples:
url(r'^$', 'prov.views.home', name='home'),
url(r'^proveedores/$', 'prov.views.proveedores', name='proveedor'),
url(r'^estado/$', 'prov.views.estado', name='estado'),
url(r'^monitor/$', 'prov.views.monitorView', name='monitor'),
url(r'^monitorv/$', 'prov.views.monitorViewV2', name='monitorv2'),
url(r'^config/(?P<idprov>\d+)/$', 'prov.views.configView',name='config'),
url(r'^admin/', include(admin.site.urls)),
)
But I receive the error Page not found.
I try to follow other snippets and always raise different errors.
I think the error is in the urls.py and in the way I pass the argument from the main.html.
Any advice or snippet will be very appreciated
Thanks in advance
First you have a form.save(commit=false) in your view without saving it later, thats mean the data is never saved into the model.
Second in your template config.html the form action is empty <form method='POST' action=''> change for <form method='POST' action='.'>
I hope that help to you.

How to realize a dynamic sidebar with Django?

I plan on creating a sidebar with changing elements (depending on the current url and authentication-status).
For example: The default sidebar shows a login and a tag cloud.
If a user is already logged in, I want to display a user menu.
If the current url is /tagcloud, I want to hide it from the sidebar.
Actually, I need a way which enables me to do something like this in a view:
def some_view(request):
if request.user.is_authenticated():
sidebar.remove('login')
sidebar.add('user_menu')
def tag_cloud(request):
sidebar.remove('tag_cloud')
Afterwards, I want to pass the sidebar (implicitly, without passing it to render_to_response) to the template where I have in mind to do something like this:
<div id="sidebar">
{{ sidebar }}
</div>
Is this possible?
You'd better do this in a context_processors.py file
That also mean you have to use a RequestContext when returning your views
def include_tagcloud(request):
if request.path == '/tagcould/':
tagcloud = Tags.objects.filter(active=True) #whatever
return {'tagcloud': tagcloud}
def include_login(request):
if request.user.is_authenticated():
loginform = MyLoginForm(request.POST)
#passing a Django form + POST data in the case of re-submit
return {'loginform' : loginform}
And then in your template :
{% if loginform %}
<form action="accounts/login/">
{{form.as_p}}
<input type="submit" name="Login">
</form>
{% endif %}
{% if tagcloud %}
{%for tag in tagcloud %}.....{%for}
{% endif %}
In this example the login form points to a fixed view,
if you want to catch the login form post on everyview, I don't know how to do
EDIT : if you don't use the CSRF features of Django, you could simply insert the login form in the base template without using any django form and pointing to a login view :
{% if user.is_authenticated %}
<form action="accounts/login/">
<input type="text" name="username"><input type="password" name="password">
<input type="submit" name="Login">
</form>
{% endif %}
Yeah, but you can use inheritance of templates as well as composition. Then include your sidebar in a parent template that is used/inherited from in all of your templates. Then it is easy to find the template for the sidebar: it's in a separate file.
Answer of #Dominique is correct but When you write something in context_processors that's load at any page of the website. That maybe makes a performance issue.
I think the right way to handle dynamic sidebar is simpletag and use where you need.
def get_sidebar():
tags = Tags.objects.filter(active=True)
latest_posts = Post.objects.all().order_by('-create_at')[:10]
html = render_to_string("sidebar.html", {
"tags": tags,
"latest_posts": latest_posts
})
return html
And now just use in template files:
<div class="col-md-4 sidebar">
{% get_sidebar %}
</div>
Also, you can pass request to simpletag to use user.is_authenticated for authenticated user access.

Categories

Resources