How do I use request.META.get('HTTP_REFERER') within template? - django

I'd like to use request.META.get('HTTP_REFERER') within template.
My template source:
<!-- this is login.html -->
{% extends "base.html" %}
{% block title %}django bookmark- login{% endblock %}
{% block head %}login{% endblock %}
{% block content %}
{% if form.errors %}
<p>try again!</p>
{% endif %}
<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="/<!-- I WANT TO USE 'HTTP_REFERER' HERE -->" />
<input type="submit" value="login" />
</form>
{% endblock %}
How what should I do?
urlpatterns = patterns('', (r'^login/$', 'django.contrib.auth.views.login'),

There's no need for get.request.META is a dictionary, and as with all dictionaries, you can perform field lookup in the template using the dot notation: {{ request.META.HTTP_REFERER }}

Add django.core.context_processors.request in your settings file in TEMPLATE_CONTEXT_PROCESSORS then you would be able to use the request in template without explicitly passing it in request context.
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.request', # this one
)
the in template you could do {{request.META.HTTP_REFERER}}

Actually the preferred way is to use the next parameter as documented here
You can do in your template something like this:
<input type="hidden" name="next" value="{{ request.GET.next }}" />

Related

How to move singup\signin templates into dropdown menu?

I have a fixed navigation and I want to add dropdown box where users can singup\in (as Twitter uses).
I tried:
# project/tempates/signup.html
{% load i18n %}
{% load account socialaccount %}
{% block head_title %}{% trans "Signup" %}{% endblock %}
{% block content %}
<h1>{% trans "Sign Up" %}</h1>
<p>{% blocktrans %}Already have an account? Then please sign in.{% endblocktrans %}</p>
<form class="signup" id="signup_form" method="post" action="{% url 'account_signup' %}">
{% csrf_token %}
{{ signupform.as_p }}
{% if redirect_field_value %}
<input type="hidden" name="{{ redirect_field_name }}" value="{{ redirect_field_value }}" />
{% endif %}
<button type="submit">{% trans "Sign Up" %} »</button>
</form>
{% endblock %}
# project/tempates/base.html
# ... a lot of basic stuff
<li class="dropdown">
<a class="dropdown-toggle" href="#" data-toggle="dropdown">Sign In <strong class="caret"></strong></a>
<div class="dropdown-menu" style="padding: 15px; padding-bottom: 0px;">
{% include './signup.html' %}
# ... rest stuff
and in dropdown box I see just the text, link to signin, and the button for confirmation of the registration.
There are no fields to enter email and passwords. As I understand, this is because no access to the form, what usually is a views' jobs. How can I get workable dropdown forms?
After 2 days of internet digging I want to summarize what I found.
There are few ways:
1. Use <form action='some address here'>. The easiest way.
To check default AllAuth forms we need to:
# ./manage.py shell
>>> import allauth.account.forms as forms
>>> f = forms.LoginForm()
>>> print(f)
Below is edited version of print(f) which is added directly to base.html
<form action="{% url 'account_login' %}" method="post">
{% csrf_token %}
<input type="hidden" name="next" value="{{ request.get_full_path }}" />
<input id="id_login" name="login" placeholder="Username or e-mail" type="text" required />
<input id="id_password" name="password" placeholder="Password" type="password" required />
<label for="id_remember">Remember Me:</label>
<input id="id_remember" name="remember" type="checkbox" />
<button type="submit">Login</button>
Forgot Password?
</form>
Method is based on the solution from ->here<-
2. Contex processor
a) Make folder your_project/your_app/context_processor. Put there 2 files - __init__.py and login_ctx.py
b) In login_ctx.py add:
from allauth.account.forms import LoginForm
def login_ctx_tag(request):
return {'loginctx': LoginForm()}
c) In project's SETTINGS add your_app.context_processors.login_ctx.login_form_ctx' inTEMPLATES` section. Something like:
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [os.path.join(BASE_DIR, 'templates'), os.path.join(BASE_DIR, 'templates', 'allauth')],
'APP_DIRS': True,
'OPTIONS': {
'debug': DEBUG,
'context_processors': [
'your_app.context_processors.login_ctx.login_form_ctx', # <- put your processor here
'django.template.context_processors.debug',
# [...other processors...]
],
},
},
]
d) In your *.html where you need add the next:
{% if not user.is_authenticated %}
<form action="{% url 'account_login' %}" method="post">
{% csrf_token %}
<input type="hidden" name="next" value="{{ request.get_full_path }}" />
{{ loginctx }}
<button type="submit">Login</button>
</form>
{% else %}
{# display something else here... (username?) #}
{% endif %}
3. Template tag
a) Make folder your_project/your_app/templatetags. Put there 2 files - __init__.py and login_tag.py
b) In login_tag.py add:
from django import template
from allauth.account.forms import LoginForm
register = template.Library()
#register.inclusion_tag('profiles/true_login.html')
def login_form_tag(current_page=None):
return {'loginform': LoginForm(),
'redirect_to': current_page}
c) In your_project/your_app/templates/your_app/ make file login_form.html with content:
{% load account %}
{% if not user.is_authenticated %}
<form action="{% url 'account_login' %}" method="post">
{% csrf_token %}
<input type="hidden" name="next" value="{{ redirect_to }}" />
{{ loginform }}
<button type="submit">Login</button>
</form>
{% else %}
{# display something else here... (username?) #}
{% endif %}
d) In any *.html you need, add at the top {% load login_tag %} and in the needed place add {% login_form_tag request.get_full_path %}
The 2nd and 3rd methods show native AllAuth form. If you need to edit it somehow using {{form}}, ->here<- in the doc you can find some examples how to do that. Want to mention, that if in the doc is shown something like:
<div class="fieldWrapper">
{{ form.subject.errors }}
{{ form.subject.label_tag }}
{{ form.subject }}
</div>
for our case form must be changed to loginctx or loginform
Also you can write your own form or inherit AllAuth and import it to context processor or templatetag as shown above.
Both methods are based on ->this solution<-
In all 3 methods redirect works as needed (return a user to the previous page, in case of success login, else redirect to original AllAuth template at site.com/account/login).
All written above can be implemented to SignUP.
Also I asked some people, how to show errors in case of wrong username\password instead of redirect to site.com/account/login, a proposition was to use AJAX, but currently this is out of my knowledge. Some base info about connection signin\up forms to default AllAuth views can be found ->here<-. If anyone could implement it, or find any tutorial, please post it here.

url-tag for url include

i use the set_language redirect view form from the docs.
urls.py
urlpatterns += patterns('',
(r'^i18n/', include('django.conf.urls.i18n')),
)
template:
<form action="/i18n/setlang/" method="post">
{% csrf_token %}
<input name="next" type="hidden" value="{{ redirect_to }}" />
<select name="language">
{% get_language_info_list for LANGUAGES as languages %}
{% for language in languages %}
<option value="{{ language.code }}">{{ language.name_local }} ({{ language.code }})</option>
{% endfor %}
</select>
<input type="submit" value="Go" />
</form>
Which is the right syntax to replace the action attribute "/i18n/setlang/" with the url-template-tag?
EDIT:
I found the right url in the include (thanks to Daniel!):
<form action="{% url django.views.i18n.set_language %}" method="post">
As the documentation says, you can enter the full path of a view as the {% url %} parameter
{% url django.views.i18n.set_language %} # quote or unquote based on your Django version
You don't care about the URL of the include, you care about the URLs inside the include. You should look at the code or the documentation for django.conf.urls.i18n to find the setlang URL you are interested in, and use that name.

Django: Redirect after posting a comment

I am trying to redirect the user back to the page where the comment was posted. I found this post on Django's site but I am doing something wrong because it won't redirect back.
Where should the input be placed to have it properly redirected?
{% load comments i18n %}
<form action="{% comment_form_target %}" method="post">{% csrf_token %}
{% if next %}<input type="hidden" name="next" value="{{ next }}" />{% endif %}
{% for field in form %}
{% if field.is_hidden %}
{{ field }}
{% else %}
{% if field.errors %}{{ field.errors }}{% endif %}
<input type="hidden" name="next" value="{% url proposal proposal.id %}" />
<p
{% if field.errors %} class="error"{% endif %}
{% ifequal field.name "honeypot" %} style="display:none;"{% endifequal %}
{% ifequal field.name "name" %} style="display:none;"{% endifequal %}
{% ifequal field.name "email" %} style="display:none;"{% endifequal %}
{% ifequal field.name "url" %} style="display:none;"{% endifequal %}
{% ifequal field.name "title" %} style="display:none;"{% endifequal %}>
<!-- {{ field.label_tag }} -->{{ field }}
</p>
{% endif %}
{% endfor %}
<p class="submit">
<!-- <button><input type="submit" name="post" value="{% trans "Send" %}" /></button> -->
<button type="submit">Send</button>
<!-- <input type="submit" name="preview" class="submit-preview" value="{% trans "Preview" %}" /> -->
</p>
</form>
Maybe you don't need to check for next variable in your template. You could try changing:
{% if next %}<input type="hidden" name="next" value="{{ next }}" />{% endif %}
to just:
<input type="hidden" name="next" value="/added/comment/page/" />
In case you use views.py, redirecting from there seems more obvious, at least for me, as it helps keep the concern away from the template:
from django.http import HttpResponseRedirect
HttpResponseRedirect("/path/to/redirect")
The problem with axel22's answer is that it requires a change to each template that requires the comment form - if you have multiple object types that can be commented on, this is not DRY.
Unfortunately, I'm also still looking for an answer that works.
if you are using {% render_comment_form for object %} tag in your template, just add something like {% url object's_named_view object.id as next %} or wrap it with {% with object.get_absolute_url as next %} ... {% endwith %} construction.
See my solution here: Django: Redirect to current article after comment post
It basically uses a view that's triggered by the comment post url which redirects back to the original referrer page.

Django: How to define "Next" within the Comments form

I am using the Django comments framework in two places on my site. After each submission, I'd like for the user to just be redirected back to the original page they were on.
How do you define the "next" variable so the user is redirected?
Information on the redirect : http://docs.djangoproject.com/en/dev/ref/contrib/comments/#redirecting-after-the-comment-post
Also, here is the form I am using. The comment.types do not work, but that is what I think I am supposed to do - define two different next inputs for each comment type (picture vs meal).
{% load comments i18n %}
<form action="{% comment_form_target %}" method="post">{% csrf_token %}
{% if comment.type == '19' %}
<input type="hidden" name="next" value="{% url meal comment.object_pk %}" />
{% endif %}
{% if comment.type == '23' %}
<input type="hidden" name="next" value="{% url picture comment.object_pk %}" />
{% endif %}
<!-- <input type="hidden" name="next" value="{{ next }}" /> -->
{% for field in form %}
{% if field.is_hidden %}
{{ field }}
{% else %}
{% if field.errors %}{{ field.errors }}{% endif %}
<p
{% if field.errors %} class="error"{% endif %}
{% ifequal field.name "honeypot" %} style="display:none;"{% endifequal %}
{% ifequal field.name "name" %} style="display:none;"{% endifequal %}
{% ifequal field.name "email" %} style="display:none;"{% endifequal %}
{% ifequal field.name "url" %} style="display:none;"{% endifequal %}
{% ifequal field.name "title" %} style="display:none;"{% endifequal %}>
<!-- {{ field.label_tag }} -->{{ field }}
</p>
{% endif %}
{% endfor %}
<p class="submit">
<button type="submit">Send</button>
<!-- <input type="submit" name="preview" class="submit-preview" value="{% trans "Preview" %}" /> -->
</p>
</form>
And then on the Meal & Picture pages I have:
<h4>Post a Message</h4>
{% render_comment_form for meal %}
<h4>Post a Message</h4>
{% render_comment_form for picture %}
Figured it out. To use the next with multiple objects, use an if statement.
{% if picture %}
<input type="hidden" name="next" value="{% url picture picture.id %}" />
{% endif %}
If you want to stay on the same page ajax is an option, you could use something like django_ajaxcomments, there are quite a few posts on others ways to do this with ajax.

Implementing a login in django

In my base.html I placed this:
{% if user.is_authenticated %}
you are logged in!
{% else %}
<h3>Login</h3>
<form action="/login/" method="post" accept-charset="utf-8">
<label for="username">Username</label><input type="text" name="username" value="" id="username" />
<label for="password">Password</label><input type="password" name="password" value="" id="password" />
<p><input type="submit" value="Login →"></p>
</form>
{% endif %}
In urls.py:
(r'^login/$', 'django.contrib.auth.views.login'),
(r'^logout/$', 'django.contrib.auth.views.logout'),
When I accessed /login I had to make a login.html file. I created templates/registration/login.html:
{% extends "base.html" %}
{% block content %}
{% if form.errors %}
<p>Your username/pass didnt match</p>
{% endif %}
{% endblock %}
I'm not seeing the username/pass, but I'm still seeing the meaning my user is not authenticated yet.
Btw, I don't have the CSRF middleware loaded. Did I miss a step or two?
One other thing, I accessed logout.html and it went into my django admin logout page. I tried making a templates/registration/logout.html but it didn't override that part. Hrm?
Are you passing the user variable to your template context? Either explicitly, or via a context processor?
Doh. Apparently my actual template had action="/login" but when I typed it in the example here it had an end slash, I re-added the end slash and that was it.