# -*- coding: utf-8 -*-
'''
Created on Jul 01, 2014
@author: tc
'''
from datetime import datetime
import json
import logging
from renkanmanager.models import Renkan
from renkanmanager.utils import LineNodePlacer, HorLineNodePlacer, renkan_copier, renkan_deleter, \
CircleNodePlacer
from renkanmanager.views import RenkanGetPut
import uuid
from django.conf import settings
from django.contrib.auth import REDIRECT_FIELD_NAME, login as auth_login, \
get_user_model
from django.contrib.auth.forms import AuthenticationForm
from django.contrib.sites.models import get_current_site
from django.core.paginator import Paginator, PageNotAnInteger, EmptyPage
from django.core.urlresolvers import reverse, reverse_lazy
from django.db.models import Q
from django.http import HttpResponse, HttpResponseBadRequest
from django.http import HttpResponseRedirect
from django.http.response import Http404
from django.shortcuts import get_object_or_404, redirect
from django.shortcuts import resolve_url
from django.template.response import TemplateResponse
from django.templatetags.static import static
from django.utils.http import is_safe_url
from django.utils.translation import ugettext as _
from django.views.decorators.cache import never_cache
from django.views.decorators.csrf import csrf_exempt, csrf_protect
from django.views.decorators.debug import sensitive_post_parameters
from django.views.generic import TemplateView, View
from django.views.generic.edit import UpdateView
from hdabo.models import Tag, Datasheet, TaggedSheet, Folder
from hdalab.forms import HdalabRenkanStateForm, HdalabRenkanFavoriteForm
from hdalab.models.dataviz import DbpediaFieldsTranslation
from hdalab.models.renkan import HdalabRenkan
from hdalab.services import change_renkan_state
from hdalab.views.ajax import filter_generic
User = get_user_model()
logger = logging.getLogger(__name__)
class BaseRenkanList(TemplateView):
def update_context(self, context, renkan_queryset):
filters = ""
filter_title = self.request.GET.get("title", "")
if(len(filter_title)>0):
renkan_queryset = renkan_queryset.filter(renkan__title__icontains=filter_title)
filters += "&title=" + filter_title
filter_username = self.request.GET.get("username", "")
if(len(filter_username)>0):
renkan_queryset = renkan_queryset.filter(renkan__owner__username=filter_username)
filters += "&username=" + filter_username
filter_state = self.request.GET.get("state", "")
if(len(filter_state)>0):
try:
filter_state = int(filter_state)
except:
pass
renkan_queryset = renkan_queryset.filter(state=filter_state)
filter_state = str(filter_state)
filters += "&state=" + filter_state
filter_startdate = self.request.GET.get("startdate", "")
if filter_startdate!="":
renkan_queryset = renkan_queryset.filter(renkan__modification_date__gt=filter_startdate)
filters += "&startdate=" + filter_startdate
filter_enddate = self.request.GET.get("enddate", "")
if filter_enddate!="":
renkan_queryset = renkan_queryset.filter(renkan__modification_date__lt=filter_enddate + " 23:59:59")
filters += "&enddate=" + filter_enddate
filter_favorite = int(self.request.GET.get('favorite', "2"))
if filter_favorite == 1:
renkan_queryset = renkan_queryset.filter(favorite=True)
elif filter_favorite == 0:
renkan_queryset = renkan_queryset.filter(favorite=False)
sort_param = self.request.GET.get('sort', "date")
order_param = self.request.GET.get('order', "desc")
sort = {"date":"renkan__modification_date", "title":"renkan__title", "state":"state", "user":"renkan__owner__username", "favorite":"favorite"}.get(sort_param, None)
if order_param=="desc":
order = "-"
opposite = "asc"
else:
order = ""
opposite = "desc"
if sort:
renkan_queryset = renkan_queryset.order_by(order + sort)
p = Paginator(renkan_queryset, settings.RENKANS_PER_PAGE)
page_nb = self.request.GET.get('page')
try:
page = p.page(page_nb)
except PageNotAnInteger:
page = p.page(1)
except EmptyPage:
page = p.page(p.num_pages)
context.update({"page": page, "sort_param":sort_param, "order_param":order_param, "opposite":opposite,
"filters":filters, "title": filter_title, "username": filter_username, "state": filter_state,
"startdate":filter_startdate, "enddate":filter_enddate, "favorite": filter_favorite})
return context
class ProfileHome(BaseRenkanList):
template_name = "profile_home.html"
def get_context_data(self, **kwargs):
return self.update_context( super(ProfileHome, self).get_context_data(**kwargs), HdalabRenkan.objects.select_related("renkan").filter(renkan__owner=self.request.user))
class RenkanPublicList(BaseRenkanList):
template_name = "renkan_list.html"
def get_context_data(self, **kwargs):
return self.update_context( super(RenkanPublicList, self).get_context_data(**kwargs), HdalabRenkan.objects.select_related("renkan", "renkan__owner").filter(state=HdalabRenkan.PUBLISHED) )
class RenkanFavoriteList(BaseRenkanList):
template_name = "renkan_list.html"
def get_context_data(self, **kwargs):
context = super(BaseRenkanList, self).get_context_data(**kwargs)
context['hide_favorite'] = True
return self.update_context(context , HdalabRenkan.objects.select_related("renkan", "renkan__owner").filter(state=HdalabRenkan.PUBLISHED, favorite=True) )
class RenkanNew(View):
def post(self, request):
rk = Renkan()
rk_id = unicode(uuid.uuid1())
rk.rk_id = rk_id
rk.owner = request.user
rk.content = '{}'
rk.title = "Nouveau Renkan "
rk.save()
hr = HdalabRenkan()
hr.renkan = rk
hr.state = HdalabRenkan.EDITION
hr.save()
return redirect("%s?rk_id=%s" % (reverse('renkan_edit'), rk_id))
class RenkanEdit(TemplateView):
template_name="renkan_edit.html"
def get_context_data(self, **kwargs):
switch_shape_url= {}
context = super(RenkanEdit, self).get_context_data(**kwargs)
# If a renkan id is set
rk_id = self.request.GET.get("rk_id", "")
if rk_id!="":
hr = get_object_or_404(HdalabRenkan.objects.select_related("renkan", "renkan__owner"), renkan__rk_id=rk_id) #.get(=rk_id)
if hr.renkan.owner!=self.request.user or hr.state!=HdalabRenkan.EDITION:
raise Exception("You are not allowed to edit this renkan")
else:
current_url = self.request.get_full_path()
switch_shape_url["current"] = current_url
if "shape=horiz" in current_url:
switch_shape_url["vert"] = current_url.replace("&shape=horiz", "&shape=vert")
switch_shape_url["circle"] = current_url.replace("&shape=horiz", "")
elif "shape=vert" in current_url:
switch_shape_url["horiz"] = current_url.replace("&shape=vert", "&shape=horiz")
switch_shape_url["circle"] = current_url.replace("&shape=vert", "")
else:
#if we generated the renkan from no filter, the url doesn't have any "?"
#we add one to create the links to the other representation
if "?" not in current_url:
current_url += "?"
switch_shape_url["horiz"] = current_url + "&shape=horiz"
switch_shape_url["vert"] = current_url + "&shape=vert"
context["switch_shape_url"] = switch_shape_url
form = AuthenticationForm(self.request)
context["form"] = form
return context
class HdalabRenkanGetPut(RenkanGetPut):
@csrf_exempt
def dispatch(self, *args, **kwargs):
return super(HdalabRenkanGetPut, self).dispatch(*args, **kwargs)
def get(self, request):
# If a renkan id is set
rk_id = request.GET.get("rk_id", "")
if rk_id!="":
rk = get_object_or_404(Renkan, rk_id=rk_id)
return HttpResponse(rk.content, content_type="application/json")
shape = request.GET.get("shape", "")
no_translate_langs = [ 'fr' ]
lang = request.GET.get('lang',request.LANGUAGE_CODE)
# Start dict for renkan json
now = datetime.now().strftime("%Y-%m-%d %H:%M")
content = {
"id": unicode(uuid.uuid1()),
"title": "",
"description": "(empty description)",
"created": now,
"updated": now,
"nodes": [],
"edges": [],
"views": [],
"users": [],
}
# category image dict
cat_dict = {u"Créateur": static("hdalab/img/category_creator.png"),
u"Datation": static("hdalab/img/category_datation.png"),
u"Discipline artistique": static("hdalab/img/category_discipline.png"),
u"Localisation": static("hdalab/img/category_localisation.png"),
u"Ecole/Mouvement": static("hdalab/img/category_movement.png")}
# category image dict
shapes = { "tag1": "polygon", "notice": "rectangle", "tag2": "star" }
# Renkan Project ID
project_id = unicode(uuid.uuid1())
# If a notice id is set
notice_id = request.GET.get("notice", "")
if notice_id!="":
notice = get_object_or_404(Datasheet, hda_id=notice_id)
# We get the ORDERED tags if we display one sheet
ordered_tags = TaggedSheet.objects.filter(datasheet=notice).select_related("tag", "tag__dbpedia_fields", "tag__category").order_by('order')[:15]
# Prepare Node placer :
np = CircleNodePlacer()
if shape=="horiz":
np = HorLineNodePlacer()
elif shape=="vert":
np = LineNodePlacer()
np.init({"datasheet": (1, 1), "tags": (2, len(ordered_tags))})
# Place notice :
content["nodes"].append({
"id": unicode(uuid.uuid1()),
"title": notice.title,
"description": notice.description,
"uri": notice.url,
"position": np.get_place("datasheet"),
"image": "http://www.histoiredesarts.culture.fr/images/pf/" + notice.hda_id + ".jpg",
"size": 0,
"project_id": project_id,
"color": "#FF0033",
#"created_by": "roster_user-84fe909f-ba37-48e6-a25f-9d2f129a95b7",
"shape": shapes["notice"]
})
notice_id = content["nodes"][0]["id"]
# Get translated labels
translations = {}
if lang not in no_translate_langs:
transqs = DbpediaFieldsTranslation.objects.filter(master__in = [ot.tag.dbpedia_fields if hasattr(ot.tag, 'dbpedia_fields') and ot.tag.dbpedia_fields else None for ot in ordered_tags], language_code = lang)
translations = dict([(trans.master_id,trans) for trans in transqs])
for ot in ordered_tags:
t = ot.tag
img_url = t.dbpedia_fields.thumbnail if hasattr(t, 'dbpedia_fields') and t.dbpedia_fields and t.dbpedia_fields.thumbnail else None
if img_url is None and t.category is not None:
img_url = cat_dict[t.category.label]
translation_obj = translations.get(t.dbpedia_fields.id, None) if t.dbpedia_fields else None
translation = {
'label': translation_obj.label if translation_obj and translation_obj.label else t.label,
'abstract': translation_obj.abstract if translation_obj and translation_obj.abstract else '',
}
content["nodes"].append({
"id": unicode(uuid.uuid1()),
"title": translation['label'],
"description": translation['abstract'],
"uri": t.wikipedia_url,
"position": np.get_place("tags"),
"image": img_url,
"size": 0,
"project_id": project_id,
"color": "#00FF33",
#"created_by": "roster_user-84fe909f-ba37-48e6-a25f-9d2f129a95b7",
"shape": shapes["tag2"]
})
# Place edges
for node in content["nodes"]:
content["edges"].append({
"id": unicode(uuid.uuid1()),
"title": "",
"description": "",
"uri": "",
"color": None,
"from": notice_id,
"to": node["id"],
"project_id": project_id,
#"created_by": "de68xf75y6hs5rgjhgghxbm217xk"
})
response = json.dumps(content)
return HttpResponse(response, content_type="application/json")
# If a folder id is set
folder_id = request.GET.get("folder", "")
if folder_id!="":
#TODO : optimize to avoid tag request on each notice
folder = get_object_or_404(Folder.objects.select_related("datasheets", "datasheets__tags"), pk=folder_id)
notices = folder.datasheets.all()
n_tags = []
notice_tag_dict = {}
tag_uuid_dict = {}
for n in notices:
notice_tag_dict[n.pk] = {"uuid":unicode(uuid.uuid1()), "tags":[] }
for t in n.tags.all()[:5]:
if t.pk not in tag_uuid_dict:
tag_uuid_dict[t.pk] = unicode(uuid.uuid1())
notice_tag_dict[n.pk]["tags"].append(tag_uuid_dict[t.pk])
n_tags.append(t)
n_tags = [t.pk for t in n_tags]
all_tags = Tag.objects.filter( pk__in=n_tags ).select_related("dbpedia_fields", "category")
# Get translated labels
translations = {}
if lang not in no_translate_langs:
transqs = DbpediaFieldsTranslation.objects.filter(master__in = [t.dbpedia_fields if hasattr(t, 'dbpedia_fields') and t.dbpedia_fields else None for t in all_tags], language_code = lang)
translations = dict([(trans.master_id,trans) for trans in transqs])
# Prepare Node placer :
np = CircleNodePlacer()
if shape=="horiz":
np = HorLineNodePlacer()
elif shape=="vert":
np = LineNodePlacer()
np.init({"datasheet": (1, len(notices)), "tags": (2, len(all_tags))})
# Place notices
for n in notices:
content["nodes"].append({
"id": notice_tag_dict[n.pk]["uuid"],
"title": n.title,
"description": n.description,
"uri": n.url,
"position": np.get_place("datasheet"),
"image": "http://www.histoiredesarts.culture.fr/images/pf/" + n.hda_id + ".jpg",
"size": 0,
"project_id": project_id,
"color": "#FF0033",
#"created_by": "roster_user-84fe909f-ba37-48e6-a25f-9d2f129a95b7",
"shape": shapes["notice"]
})
# Place tags
for t in all_tags:
img_url = t.dbpedia_fields.thumbnail if hasattr(t, 'dbpedia_fields') and t.dbpedia_fields and t.dbpedia_fields.thumbnail else None
translation_obj = translations.get(t.dbpedia_fields.id, None) if t.dbpedia_fields else None
translation = {
'label': translation_obj.label if translation_obj and translation_obj.label else t.label,
'abstract': translation_obj.abstract if translation_obj and translation_obj.abstract else '',
}
if img_url is None and t.category is not None:
img_url = cat_dict[t.category.label]
content["nodes"].append({
"id": tag_uuid_dict[t.pk],
"title": translation['label'],
"description": translation['abstract'],
"uri": t.wikipedia_url,
"position": np.get_place("tags"),
"image": img_url,
"size": 0,
"project_id": project_id,
"color": "#00FF33",
#"created_by": "roster_user-84fe909f-ba37-48e6-a25f-9d2f129a95b7",
"shape": shapes["tag2"]
})
# Place edges
for n_pk in notice_tag_dict:
for tag_id in notice_tag_dict[n_pk]["tags"]:
content["edges"].append({
"id": unicode(uuid.uuid1()),
"title": "",
"description": "",
"uri": "",
"color": None,
"from": notice_tag_dict[n_pk]["uuid"],
"to": tag_id,
"project_id": project_id,
#"created_by": "de68xf75y6hs5rgjhgghxbm217xk"
})
response = json.dumps(content)
return HttpResponse(response, content_type="application/json")
# Otherwise we build the datas
# Get tags and countries
labels = request.GET.get("label", "").split(",")
countries = request.GET.get("country", "").split(",")
period = request.GET.get("period", None)
# Tags arrive with french label, countries with dbpedia uri
label_list = [t for t in labels if t!=""]
country_list = [c for c in countries if c!=""]
all_tags = Tag.objects.filter( Q(label__in=label_list) | Q(dbpedia_uri__in=country_list) ).select_related("dbpedia_fields", "category")
# Get datasheets from ajax filter search
temp_fitler = filter_generic(lang, period, ",".join(label_list), ",".join(country_list), content_count=18)
filter_output = json.loads(temp_fitler)
filter_output_to_bin = json.loads(temp_fitler)
#Keep only the 8 first ressources to create the graph
#the 10 next are sent to the bins
for i in range(len(filter_output["contents"])):
if (i < 8):
del filter_output_to_bin["contents"][0]
else:
del filter_output["contents"][8]
content["bins"] = {
"type": "ResourceList",
"title": _("Plus de Ressources"), #TODO: Translate
"list": filter_output_to_bin["contents"]
}
# Prepare other tags
related_tags = []
all_labels = [t.label for t in all_tags]
title = "Recherche " + ", ".join(all_labels)
if period:
title += ", " + _("Period") + " " + period
content["title"] = title
related_tags_dict = {}
for c in filter_output["contents"]:
c["id"] = unicode(uuid.uuid1())
related_tags_dict[c["id"]] = []
for t in c["tags"]:
if t["label"] not in all_labels and t["order"]<6:
thumbnail_url = ""
for tt in filter_output["tags"]:
if tt["label"]==t["label"]:
thumbnail_url = tt["thumbnail"]
related_tags.append({"label": t["label"], "thumbnail":thumbnail_url, "id":t["id"], "url":t["url"], 'wkpd_url': t['wkpd_url']})
all_labels.append(t["label"])
related_tags_dict[c["id"]].append(t["id"])
# If possible, we search a dbpedia_fields thumbnail or category thumbnail for related tags
r_tags = [t["label"] for t in related_tags if t["thumbnail"] is None or t["thumbnail"]=="" ]
r_tags = Tag.objects.filter( label__in=r_tags ).select_related("dbpedia_fields", "category")
r_tags_dict = {}
for t in r_tags:
img_url = t.dbpedia_fields.thumbnail if hasattr(t, 'dbpedia_fields') and t.dbpedia_fields and t.dbpedia_fields.thumbnail else None
if img_url is None and t.category is not None:
img_url = cat_dict[t.category.label]
if img_url:
r_tags_dict[t.label] = img_url
# Populate related_tags with found image urls
for t in related_tags:
if (t["thumbnail"] is None or t["thumbnail"]=="") and (t["label"] in r_tags_dict):
t["thumbnail"] = r_tags_dict[t["label"]]
# Prepare Node placer :
np = CircleNodePlacer()
if shape=="horiz":
np = HorLineNodePlacer()
elif shape=="vert":
np = LineNodePlacer()
len_tags = len(all_tags)
if period:
len_tags += 1
np.init({"tags": (1, len_tags), "datasheet": (2, len(filter_output["contents"])), "related": (3, len(related_tags)), "northwest":(3 if shape=="circle" else 1, 1)})
#get tag abstract and label translations
tags_id = [t.id for t in all_tags] + [t['id'] for t in related_tags]
translations = {}
transqs = DbpediaFieldsTranslation.objects.filter(master__tag__in = tags_id, language_code = lang)
translations = dict([(trans.master.tag.id,trans) for trans in transqs])
for t in all_tags:
img_url = t.dbpedia_fields.thumbnail if hasattr(t, 'dbpedia_fields') and t.dbpedia_fields and t.dbpedia_fields.thumbnail else None
if img_url is None and t.category is not None:
img_url = cat_dict[t.category.label]
translation_obj = translations.get(t.id, None)
translation = {
'label': filter_output["tagtranslations"][t.label] if t.label in filter_output["tagtranslations"] else t.label,
'abstract': translation_obj.abstract if translation_obj else ""
}
content["nodes"].append({
"id": unicode(uuid.uuid1()),
"title": translation['label'],
"description": translation['abstract'],
"uri": t.wikipedia_url,
"position": np.get_place("tags"),
"image": img_url,
"size": 0,
"project_id": project_id,
"color": None,
#"created_by": "roster_user-84fe909f-ba37-48e6-a25f-9d2f129a95b7",
"shape": shapes["tag1"]
})
if period:
content["nodes"].append({
"id": unicode(uuid.uuid1()),
"title": _("Period") + " " + period,
"description": "",
"uri": "",
"position": np.get_place("tags"),
"image": cat_dict[u"Datation"],
"size": 0,
"project_id": project_id,
"color": None,
#"created_by": "roster_user-84fe909f-ba37-48e6-a25f-9d2f129a95b7",
"shape": shapes["tag1"]
})
for c in filter_output["contents"]:
content["nodes"].append({
"id": c["id"],
"title": c["title"],
"description": c["description"],
"uri": c["url"],
"position": np.get_place("datasheet"),
"image": "http://www.histoiredesarts.culture.fr/images/pf/" + c["hda_id"]+ ".jpg",
"size": 0,
"project_id": project_id,
"color": "#FF0033",
#"created_by": "roster_user-84fe909f-ba37-48e6-a25f-9d2f129a95b7",
"shape": shapes["notice"]
})
for t in related_tags:
translation_obj = translations.get(t['id'], None)
translation = {
'label': filter_output["tagtranslations"][t["label"]],
'abstract': translation_obj.abstract if translation_obj else ""
}
content["nodes"].append({
"id": t["id"],
"title": translation['label'],
"description": translation['abstract'],
"uri": t["wkpd_url"],
"position": np.get_place("related"),
"image": t["thumbnail"],
"size": 0,
"project_id": project_id,
"color": "#00FF33",
#"created_by": "roster_user-84fe909f-ba37-48e6-a25f-9d2f129a95b7",
"shape": shapes["tag2"]
})
for c_id in related_tags_dict:
for tag_id in related_tags_dict[c_id]:
content["edges"].append({
"id": unicode(uuid.uuid1()),
"title": "",
"description": "",
"uri": "",
"color": None,
"from": c_id,
"to": tag_id,
"project_id": project_id,
#"created_by": "de68xf75y6hs5rgjhgghxbm217xk"
})
response = json.dumps(content)
return HttpResponse(response, content_type="application/json")
def post(self, request):
rk_id = request.GET.get("rk_id", "")
#data = json.loads(request.body)
#logger.debug(data["edges"])
#logger.debug(data["nodes"])
#logger.debug(request.user.is_authenticated())
#logger.debug(request.user.is_anonymous())
if rk_id!="":
rk = get_object_or_404(Renkan, rk_id=rk_id)
if rk.owner!=request.user:
return HttpResponseBadRequest("You are not allowed to edit this renkan")
rk.content = request.body
data = json.loads(request.body)
if "title" in data:
rk.title = data["title"]
rk.save()
return HttpResponse("SAVED")
else:
# if rk_id was not a get parameter AND if it is set in json data AND if user is authenticated
# Then we can save the renkan
data = json.loads(request.body)
if "id" in data:
rk_id = data["id"]
if rk_id != "" and Renkan.objects.filter(rk_id=rk_id).count()==0 and request.user.is_authenticated():
rk = Renkan()
rk.rk_id = rk_id
rk.title = data["title"] if "title" in data else ""
rk.content = request.body
rk.owner = request.user
rk.save()
hr = HdalabRenkan()
hr.renkan = rk
hr.state = HdalabRenkan.EDITION
hr.save()
return HttpResponse("rk_id=" + rk_id)
return HttpResponse("NOT SAVED")
class HdalabRenkanCopy(View):
def post(self, request, rk_id):
rk = renkan_copier(request.user, rk_id)
hr = HdalabRenkan()
hr.renkan = rk
hr.state = HdalabRenkan.EDITION
hr.save()
if "next" in request.POST:
return redirect(request.POST["next"])
return redirect(reverse('profile_home'))
class HdalabRenkanDelete(View):
def post(self, request, rk_id):
try:
hr = HdalabRenkan.objects.get(renkan__rk_id=rk_id)
except:
raise Http404('Renkan not found')
renkan_deleter(request.user, rk_id)
hr.delete()
if "next" in request.POST:
return redirect(request.POST["next"])
return redirect(reverse('profile_home'))
class HdalabRenkanModerate(View):
def post(self, request, rk_id):
form = HdalabRenkanStateForm(request.POST)
if form.is_valid():
logger.debug("FORM DATA %r", form.cleaned_data)
renkan_hda = get_object_or_404(HdalabRenkan.objects.select_related(), renkan__rk_id=rk_id)
change_renkan_state(renkan_hda, form.cleaned_data['state'], form.cleaned_data['message'], request.user)
next_url = form.cleaned_data.get('next', None)
if next_url:
return redirect(next_url)
else:
redirect(reverse('profile_home'))
else:
logger.debug("FORM INVALID %r : %r", request.POST, form.errors)
return HttpResponseBadRequest("State form invalid")
class HdalabRenkanFavorite(View):
def post(self, request, rk_id):
form = HdalabRenkanFavoriteForm(request.POST)
if form.is_valid():
renkan_hda = get_object_or_404(HdalabRenkan.objects.select_related(), renkan__rk_id=rk_id)
renkan_hda.favorite = form.cleaned_data['favorite']
renkan_hda.save()
return HttpResponse(
json.dumps({'status': 'ok', 'renkan': {'rk_id': renkan_hda.renkan.rk_id, 'favorite': renkan_hda.favorite}}),
content_type="application/json"
)
class UserProfileUpdate(UpdateView):
model = User
fields = ['email']
template_name_suffix = '_update_form'
def get_object(self, queryset=None):
return self.request.user
def get_success_url(self):
return reverse('profile_home')
# Function copied from django.contrib.auth.views to simplify ajax login
@sensitive_post_parameters()
@csrf_protect
@never_cache
def ajax_login(request, template_name='ajax_identification/ajax_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(request, 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())
return HttpResponseRedirect(redirect_to)
else:
form = authentication_form(request)
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)