How can i render a specific Django admin page from a view? - django

I know that can reverse to admin pages from a template by doing this:
{% url 'admin:index' %}
or
{% url 'admin:app_model_add' %}
But how can i render an admin page using the render function in my view?
When i do
render(request, template_name='admin/index.html')
I get a blank looking admin page with the message "You do not have permission to view or edit anything"
Furthermore, I am not sure what the syntax would be to render a specific admin template, i.e. the equivalent of using this reverse in a template:
admin:app_model_add
is not something like this in a view:
render(request, template_name='admin/app_model_add.html')

In fact i shouldn't to try to render an admin page, i should redirect to it.
so in my view I should be using:
redirect(to=reverse('admin:index'))
or
redirect(to=reverse('admin:app_model_add'))

Related

How to add Wagtail 'admin' menu to custom templates?

On templates that derive from the Wagtail Page model, there is a small Wagtail icon/menu in the lower right corner. This provides a quick way to edit the page and/or jump to the Wagtail Admin. However, this menu does not appear on custom view templates that are not derived from Wagtail Page model.
How can I tell Wagtail to display the small menu on my frontend templates, so the pages have consistent navigation?
The standard Wagtail user bar is rendered by placing in your template:
{% load wagtailuserbar %}
{% wagtailuserbar 'top-left' %}
I typically just put the above in base.html. The 'top-left' designation, of course, tells the template tag where to render the user bar. Reference
However, the wagtailuserbar is only rendered for Wagtail pages. What you want to do is render the user bar with only the Go to Wagtail Admin option (because no other options would be relevant). Therefore, you could create your own template tag and place it in base.html beside the wagtailuserbar. You would set it up so that it renders if there IS NO page in the context (the wagtailuserbar template tag checks to make sure there IS a page in the context). To create your tag, just start with the code from wagtailuserbar.py and modify it to create a template tag called wagtailuserbar_admin_only (untested):
from django import template
from django.template.loader import render_to_string
from wagtail.admin.templatetags.wagtailuserbar import get_page_instance
from wagtail.admin.userbar import (AdminItem)
#register.simple_tag(takes_context=True)
def wagtailuserbar_admin_only(context, position='bottom-right'):
# Find request object
try:
request = context['request']
except KeyError:
return ''
# Don't render without a user because we can't check their permissions
try:
user = request.user
except AttributeError:
return ''
# Don't render if user doesn't have permission to access the admin area
if not user.has_perm('wagtailadmin.access_admin'):
return ''
# Only render if the context does NOT contain a variable referencing a saved page
page = get_page_instance(context)
if page:
return ''
# Render the items
rendered_items = [AdminItem()]
# Render the userbar items
return render_to_string('wagtailadmin/userbar/base.html', {
'request': request,
'items': rendered_items,
'position': position,
})
Then, to use in templates, place in base.html:
{% load wagtailuserbar_admin_only %}
{% wagtailuserbar_admin_only 'top-left' %}

Dynamic redirect url after login [duplicate]

I'm trying to build a simple website with login functionality very similar to the one here on SO.
The user should be able to browse the site as an anonymous user and there will be a login link on every page. When clicking on the login link the user will be taken to the login form. After a successful login the user should be taken back to the page from where he clicked the login link in the first place.
I'm guessing that I have to somehow pass the url of the current page to the view that handles the login form but I can't really get it to work.
EDIT:
I figured it out. I linked to the login form by passing the current page as a GET parameter and then used 'next' to redirect to that page. Thanks!
EDIT 2:
My explanation did not seem to be clear so as requested here is my code:
Lets say we are on a page foo.html and we are not logged in. Now we would like to have a link on foo.html that links to login.html. There we can login and are then redirected back to foo.html.
The link on foo.html looks like this:
<a href='/login/?next={{ request.path }}'>Login</a>
Now I wrote a custom login view that looks somewhat like this:
def login_view(request):
redirect_to = request.REQUEST.get('next', '')
if request.method=='POST':
#create login form...
if valid login credentials have been entered:
return HttpResponseRedirect(redirect_to)
#...
return render_to_response('login.html', locals())
And the important line in login.html:
<form method="post" action="./?next={{ redirect_to }}">
So yeah thats pretty much it, hope that makes it clear.
You do not need to make an extra view for this, the functionality is already built in.
First each page with a login link needs to know the current path, and the easiest way is to add the request context preprosessor to settings.py (the 4 first are default), then the request object will be available in each request:
settings.py:
TEMPLATE_CONTEXT_PROCESSORS = (
"django.core.context_processors.auth",
"django.core.context_processors.debug",
"django.core.context_processors.i18n",
"django.core.context_processors.media",
"django.core.context_processors.request",
)
Then add in the template you want the Login link:
base.html:
Login
This will add a GET argument to the login page that points back to the current page.
The login template can then be as simple as this:
registration/login.html:
{% block content %}
<form method="post" action="">
{{form.as_p}}
<input type="submit" value="Login">
</form>
{% endblock %}
To support full urls with param/values you'd need:
?next={{ request.get_full_path|urlencode }}
instead of just:
?next={{ request.path }}
This may not be a "best practice", but I've successfully used this before:
return HttpResponseRedirect(request.META.get('HTTP_REFERER','/'))
Django's built-in authentication works the way you want.
Their login pages include a next query string which is the page to return to after login.
Look at http://docs.djangoproject.com/en/dev/topics/auth/#django.contrib.auth.decorators.login_required
I linked to the login form by passing the current page as a GET parameter and then used 'next' to redirect to that page. Thanks!
I encountered the same problem. This solution allows me to keep using the generic login view:
urlpatterns += patterns('django.views.generic.simple',
(r'^accounts/profile/$', 'redirect_to', {'url': 'generic_account_url'}),
)
In registration/login.html (nested within templates folder) if you insert the following line, the page will render like Django's original admin login page:
{% include "admin/login.html" %}
Note: The file should contain above lines only.
See django docs for views.login(), you supply a 'next' value (as a hidden field) on the input form to redirect to after a successful login.
You can also do this
<input type="hidden" name="text" value="{% url 'dashboard' %}" />

django-registration: how do I check whether the user is logged in before displaying a page

I followed this page to set up a django registration site. It's pretty awesome, and registration and authentication are nicely wrapped.
But, it doesn't show me, how do I check if a user is logged in, who this user is, before displaying a webpage? and how do I direct the user to a new page after logged in?
Thanks!
In a view, you can use if request.user.is_authenticated(): and the variable for the current user is request.user
In a template, you can use {% if user.is_authenticated %} and the variable for the current user is user
For redirecting a user after logging in, you can set up LOGIN_REDIRECT_URL variable in settings.py
In .py documents
You can either use this inside every view
if not request.user.is_authenticated:
#do something
or this just before every view
#login_required
Remember that this one requires importing from django.contrib.auth.decorators import login_required
and you may also want to write LOGIN_URL = "/loginurl/" in your settings.py to get non-logged users redirected to an specific URL instead of the default one accounts/login)
In .html documents
{% if not user.is_authenticated %}
Login is required
{% endif %}
Redirecting after logging in
You can either modify LOGIN_REDIRECT_URL in settings.py
or redirect("/indexpage") after the user has been logged in.
This last one requires importing from django.shortcuts import redirect
You can also use a login required decorator before your view :
#login_required()
It redirects a user to the login page if a non logged in user tries to access your view
You will find more on this page :
https://docs.djangoproject.com/en/dev/topics/auth/default/#topic-authorization

Showing the logged-in user inside base.html (django)

Is there a way to access the logged in user's firstname inside the base.html file?
I'm trying to do this, because i want to display who is currently logged in on the navigation bar, but it won't access the user's information, nor will it correctly check if the user is authenticated.
html inside base.html
Hi there,
{% if user.is_authenticated %}
{{user.first_name}}
{% else %}
Stranger
{% endif %}
request.user gives you the user object that is currently logged in. So you have full access to all the attributes and methods the User class has. To get the first_name, you can do {{ request.user.first_name }}. To get the full name you use {{ request.user.get_full_name }}.
If you use [RequestContext][1], by default you get user instance in your templates so you can use it as for its attributes as {{user.first_name}} and others. The user will be same a currently authenticated user which is also available in request.user in the views.
The RequestContext by default adds some default template contexts defined in TEMPLATE_CONTEXT_PROCESSORS in your settings.py.
In your view, you can use it as
#your view code
....
#send response by rendering the template and use Requestcontext while rendering template
return render_to_response('polls/detail.html', {'poll': p},
context_instance=RequestContext(request))
Reference - Django Tutorial 04

How can I generate a url to a particular item in the Django Admin Site from a view?

I would like to make a link that would take the user to a particular item in the admin site (assuming they have the correct permissions).
Something like: https://mysite/admin/app/model/id/
Can this be done with reverse?
You can get the url in the view, using reverse,
object_change_url = reverse('admin:myapp_mymodel_change', args=(obj.id,))
Or in the template, using the url tag
{% url 'admin:myapp_mymodel_change' obj.id %}
or
{% load admin_urls %}
{% url opts|admin_urlname:'change' obj.id %}">
Note the above url tag syntax is for Django >= 1.5.
For more information, see the Django docs on reversing admin urls.