How to reset user password from the admin interface - django

In my website, I want to let the admins reset the password of any user.
With reset I mean exactly what the password_reset view does (under contrib.auth): Send a confirmation link to that user email.
How would be the best way of doing that? Is there an already app/snippet that does that?
Edit:
Let's suppose user john is an admin. What I want is to let john reset any user's password through the admin interface. For example, to reset max password, he will just go to the max user, and click on any link to reset his password.

What I finally did was to add a custom ModelAdmin:
from django.contrib.auth.forms import PasswordResetForm
from django.contrib.auth.admin import UserAdmin
class CustomUserAdmin(UserAdmin):
...
def reset_password(self, request, user_id):
if not self.has_change_permission(request):
raise PermissionDenied
user = get_object_or_404(self.model, pk=user_id)
form = PasswordResetForm(data={'email': user.email})
form.is_valid()
form.save(email_template_name='my_template.html')
return HttpResponseRedirect('..')
def get_urls(self):
urls = super(UserAdmin, self).get_urls()
my_urls = patterns('',
(r'^(\d+)/reset-password/$',
self.admin_site.admin_view(self.reset_password)
),
)
return my_urls + urls
and I also had to override the change_form.html template, like this:
{% extends "admin/change_form.html" %}
{% load i18n %}
{% block object-tools %}
{% if change %}{% if not is_popup %}
<ul class="object-tools">
{# You can also give a name to that pattern and refer to it below using 'url' #}
<li>Reset password</li>
<li>{% trans "History" %}</li>
{% if has_absolute_url %}
<li><a href="../../../r/{{ content_type_id }}/{{ object_id }}/" class="viewsitelink">
{% trans "View on site" %}</a>
</li>
{% endif%}
</ul>
{% endif %}{% endif %}
{% endblock %}
The result looks like this:
If you want a more detailed explanation, I blogged about it.

The passreset app just exposes the django views via urls.py, and adjusts the login template to show a "Forgot my password" link.
The built-in django password reset views and templates are meant for self-reset. I guess the reset form could be prepopulated with a different user's email address (in the query string) but you'd still need to make adjustments such as changing the email template - "You're receiving this e-mail because you requested a password reset for your user account" is probably not what you want:
https://code.djangoproject.com/browser/django/trunk/django/contrib/admin/templates/registration/password_reset_email.html
Therefore you should expose the views at different URLs if you want to include self-reset as well.
Hook the django views into urls.py like so:
urlpatterns += patterns('django.contrib.auth.views',
url(r'^accounts/password/reset/$',
'password_reset',
name='password-reset'),
url(r'^accounts/password/reset/done/$',
'password_reset_done',
name='password-reset-done'),
url(r'^accounts/password/reset/confirm/(?P<uidb36>[-\w]+)/(?P<token>[-\w]+)/$',
'password_reset_confirm',
name='password-reset-confirm'),
url(r'^accounts/password/reset/complete/$',
'views.password_reset_complete',
name='password-reset-complete')
)
and where you want to make adjustments, pass in e.g. your own email template:
url(r'^/accounts/password/reset/$',
'password_reset',
{'email_template_name': 'my_templates/password_reset_email.html'}
name='password-reset'),
The "password_reset" view has more parameters you can tweak:
https://docs.djangoproject.com/en/dev/topics/auth/#module-django.contrib.auth.views
("post_reset_redirect" comes to mind as another one for your purposes)
To show a corresponding link you'd either change the User admin (careful, already registered - unregister then register your own, subclassed plus additional link field) or the change_form template itself.
I'm unaware of an app that provides this out-of-the-box, so I upvoted the question :-).

Yep, there is an app for that. Check here:
https://github.com/bendavis78/django-passreset

Related

Django - add link with custom admin page href

In my Django project, I have created a custom admin page for an app via the get_urls() method. I'd like to add a link to the app's main model index view that will take users to this custom page - however, I'm having some trouble creating this link element correctly and I don't seem to be able to piece together the right way to do it - I'm just left with a Reverse for 'export' not found. 'export' is not a valid view function or pattern name. error.
I've set up the admin for the app like so:
# my_project/observations/admin.py
from django.template.response import TemplateResponse
from django.urls import path
class ObservationAdmin(SimpleHistoryAdmin, SoftDeletionModelAdmin):
change_list_template = 'export_link.html'
def get_urls(self):
urls = super().get_urls()
custom_urls = [
path('export/', self.admin_site.admin_view(self.export_view), name='export')
]
return custom_urls + urls
def export_view(self, request):
context = dict(
self.admin_site.each_context(request),
)
return TemplateResponse(request, 'export.html', context)
and the two templates that are referenced:
# my_project/observations/templates/export.html
{% extends "admin/base_site.html" %}
{% block content %}
<div>
Some custom content
</div>
{% endblock %}
# my_project/observations/templates/export_link.html
{% extends 'admin/change_list.html' %}
{% block object-tools-items %}
<li>
Export
</li>
{{ block.super }}
{% endblock %}
Navigating directly to http://localhost:8000/admin/observations/observation/export/ works perfectly, I see the custom content page exactly as I want it... so the issue I'm striking is with the link template - I get the Reverse... error when I navigate to the model index page.
Perhaps the argument I'm passing to url is incorrect, or I need to register that URL elsewhere - but I don't quite know. The other examples of link elements like this that I've been able to find don't reference URLs created via the admin class' get_urls() method - so any guidance on this would be greatly appreciated.
Thanks very much, let me know if there's any other info that I can provide to help sort this out.
I think the problems is in missing namespace in your export_link.html template. Instead of:
Export
try:
Export

Prevent logged in user variable from changing in different context in django

I'm using Django 1.8.4 and Django-registration-redux for handling user registration. My problem is:
when a user logged in, i.e. james, I want to show his username in toolbar. But the problem is when I visit another user's profile,i.e. mike, the username in toolbar also changes to mike. Which is absolutely forbidden.
I'm getting logged in user as an object in my views to check if the logged in user is same as user's profile is currently visited.
I'm not sure if I should prevent request.user to change in different contexts or there's a problem in my codes:
urls.py
url(r'^users/(?P<slug>\w+)/$', UserProfileDetailView.as_view(), name="profile"),
views.py
class UserProfileDetailView(DetailView):
model = get_user_model()
slug_field = "username"
template_name = "user_detail.html"
def get_object(self, queryset=None):
user = super(UserProfileDetailView, self).get_object(queryset)
UserProfile.objects.get_or_create(user=user)
return user
base.html
{% if user.is_authenticated %}
Submit Link |
Logout |
<b>{{ user.username }}</b>
{% else %}
Register |
Login
{% endif %}
user_detail.html
{% if object == request.user and request.user.is_authenticated %}
<p><a href='{% url "edit_profile" %}'>Edit My Profile</a></p>
{% endif %}
There are 2 users in your context:
object (or user - DetailView will also return current object on lowercased model name) this is user you're viewing
request.user - this is current logged in user
You've used user.name in toolbar instead of request.user.name. That is causing issues.

How get current user in a template tag?

How can i get the current user in a django template tags? (request object is not accessible)
Or how can i access to request object?
If you want to access the current user in a template tag, you must pass it as a parameter in the templates, like so:
{% my_template_tag user %}
Then make sure your template tag accepts this extra parameter. Check out the documentation on this topic. You should also check out simple tags.
The user is always attached to the request, in your templates you can do the following:
{% if user.is_authenticated %}
{% endif %}
You don't have to specify "request" to access its content
UPDATE:
Be aware: is_authenticated() always return True for logged user (User objects), but returns False for AnonymousUser (guest users). Read here: https://docs.djangoproject.com/en/1.7/ref/contrib/auth/
This question was already answered here:
{% if user.is_authenticated %}
<p> Welcome '{{ user.username }}'</p>
{% else %}
Login
{% endif %}
and make sure you have the request template context processor installed in your settings.py:
TEMPLATE_CONTEXT_PROCESSORS = (
...
'django.core.context_processors.request',
...
)
Note:
Use request.user.get_username() in views & user.get_username in
templates. Preferred over referring username attribute directly.
Source
This template context variable is available if a RequestContext is used.
django.contrib.auth.context_processors.auth is enabled by default & contains the variable user
You do NOT need to enable django.core.context_processors.request template context processor.
Source : https://docs.djangoproject.com/en/dev/topics/auth/default/#authentication-data-in-templates
Suppose you have a profile page of every registered user, and you only want to show the edit link to the owner of the profile page (i.e., if the current user is accessing his/her profile page, the user can see the edit button, but the user can't see the edit button on other user's profile page.
In your html file:
<h2>Profile of {{ object.username }}</h2>
{% if object.username == user.username %}
Edit
{% endif %}
Then your urls.py file should contain:
from django.urls import path
from .views import ProfileUpdateView
urlpatterns = [
...
path('<int:pk>/profile/update', ProfileUpdateView.as_view(), name = 'profile_update'),
...
]
considering you have appropriate ProfileUpdateView and appropriate model

Django - Showing different templates to admins

In Django what's the best way to implement templates with extra functionality for users with 'admin' permissions.
I'm not sure if I should create a set of completely different views specific for admins or integrate it into my existing views and templates like 'if user is an admin' everywhere.
Is there a standard way to do this in Django?
This will show the stuff only if you are active and staff not admin:
{% if request.user.is_active and request.user.is_staff %}
{% include "foo/bar.html" %}
{% endif %}
If you wanna show only and ONLY for admin you have to do that:
{% if request.user.is_superuser %}
ADD your admin stuff there.
{% endif %}
Differences about these fields here.
If you have the the user available in template context you can do:
{% if user.is_active and user.is_staff %}
Only the admin will see this code. For example include some admin template here:
{% include "foo/bar.html" %}
{% endif %}
User will be available in your template f you use RequestContext and your TEMPLATE_CONTEXT_PROCESSORS setting contains django.contrib.auth.context_processors.auth, which is default. See authentication data in templates as reference.
I'm an advocate of keeping as much logic out of the view layer (speaking generally about the MVC Design Pattern). So why not use decorators to direct your user to different views based upon their privilege? In your urls.py, define a pattern for admins:
url(r'^admin/$', 'user.views.admin_index'),
#do so for your other admin views, maybe more elegantly than this quick example
Then define a decorator to kick the user out if they're not an admin
def redirect_if_not_admin(fn):
def wrapper(request):
if request.user.is_staff():
return fn(request)
#or user.is_superuser(), etc
else:
return HttpResponseRedirect('/Permission_Denied/')
return wrapper
And in your admin views
#redirect_if_not_admin
def index(request):
##do your thing
It's more code than the other two answers, which are not wrong. It's just a personal preference to keep clutter down in the views.

django problem:captured parameter in parent urlconf , incude() and reverse match

If I want to have django app called app1 which can make a user post note to someone's page and to his/her own page.
And if the user is logged in ,no need using username in the url, but the username parameter in url can be acts as parent in urlconf.
To make it clear:
urls.py
urlpatterns = patterns(''
#if registered user/anonymous user visit someone's page
url(r'^/foo/users/(?P<username>\w+)/app1/',include('app1.urls', namespace='myapp1')),
#if user is logged in in his own page
url(r'^app1/', include('app1.urls', namespace='myapp1')),
...
)
app1/urls.py
urlpatterns = patterns('',
# I expect this pattern receives the username parameter from above
url(r'^note/add/$', app1_views.add_note,
name='add_note'),
url(r'^note/add/$', app1_views.add_note,
{ 'username':None}, name='add_note_own'),
...
...
)
app1/views.py
def add_note(request, username=None):
...
...
First question:
Now for example john is logged in and on jack's notes page john want to post a note.
I want to be able to do something like this or near something like this:
template app1/notes.html
{% if request.user.is_authenticated %}
{%if in his/her own note page %}
add note Expected generated url: www.domain.com/app1/add
{%else}
add note Expected generated url: www.domain.com/foo/jack/app1/add
{%endif%}
{% endif %}
Is this possible?
Another thing,
if john wrote note in jack's page, and django gives the note id == 3,
so to show that note, only these urls are valid:
www.example.com/foo/jack/app1/3
www.example.com/foo/app1/3 (if jack logged in)
Second question:
what I want to achieve is reverse match can accept captured parameter up to to the
parent urlconf when include() is involved in url configuration.
Can this be done?
Or if you get what I mean and can provide simpler solution , please do so :)
sorry if this post is confusing, I am confused myself.
Thanks alot for the patience.
I'm using django 1.2.5
you need to pass an username, one example can be:
urlpatterns = patterns('',
# I expect this pattern receives the username parameter from above
url(r'^note/add/(?P<username>[^/]+)/$', app1_views.add_note, name='add_note'),
# username is an optional argument, so no need to pass it
url(r'^note/add/$', app1_views.add_note, name='add_note_own'),
)
and then in template:
{% if request.user.is_authenticated %}
{% if page.owner == request.user %}
add note
{% else %}
add note to {{ request.user.username }}
{% endif %}
{% endif %}