Completed
Push — master ( 28b0ba...17cdbf )
by Andrea
01:44
created

search_service()   F

Complexity

Conditions 10

Size

Total Lines 40

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 40
rs 3.1304
cc 10

How to fix   Complexity   

Complexity

Complex classes like search_service() often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

1
#################################################################
2
# MET v2 Metadate Explorer Tool
3
#
4
# This Software is Open Source. See License: https://github.com/TERENA/met/blob/master/LICENSE.md
5
# Copyright (c) 2012, TERENA All rights reserved.
6
#
7
# This Software is based on MET v1 developed for TERENA by Yaco Sistemas, http://www.yaco.es/
8
# MET v2 was developed for TERENA by Tamim Ziai, DAASI International GmbH, http://www.daasi.de
9
# Current version of MET has been revised for performance improvements by Andrea Biancini,
10
# Consortium GARR, http://www.garr.it
11
#########################################################################################
12
13
import re, time
14
import pytz
15
import simplejson as json
16
from urllib import unquote
17
from datetime import datetime
18
from dateutil import tz
19
20
from django.conf import settings
21
from django.db.models import Max, Count
22
from django.contrib import messages
23
from django.contrib.auth import login, logout
24
from django.contrib.auth.models import User
25
from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger
26
from django.core.urlresolvers import reverse
27
from django.http import HttpResponse, HttpResponseRedirect, HttpResponseBadRequest
28
from django.shortcuts import render_to_response, get_object_or_404
29
from django.template import RequestContext
30
from django.utils.translation import ugettext_lazy as _
31
from django.utils import timezone
32
33
from chartit import DataPool, Chart
34
35
from met.metadataparser.decorators import user_can_edit
36
from met.metadataparser.models import Federation, Entity, EntityStat, TOP_LENGTH, FEDERATION_TYPES
37
from met.metadataparser.forms import (FederationForm, EntityForm, EntityCommentForm,
38
                                      EntityProposalForm, ServiceSearchForm, ChartForm)
39
40
from met.metadataparser.summary_export import export_summary
41
from met.metadataparser.query_export import export_query_set
42
from met.metadataparser.entity_export import export_entity
43
from met.metadataparser.xmlparser import DESCRIPTOR_TYPES
44
from met.metadataparser.utils import send_mail
45
46
if settings.PROFILE:
47
    from silk.profiling.profiler import silk_profile as profile
48
else:
49
    from met.metadataparser.templatetags.decorators import noop_decorator as profile
50
51
RESCUE_SLASH = re.compile(r"^(http(?:|s):/)([^/])")
52
53
def increment_current_toplength(request):
54
    current_top_length = request.session.get('currentTopLength', TOP_LENGTH)
55
    current_top_length += TOP_LENGTH
56
57
    if current_top_length > Entity.objects.all().count():
58
        current_top_length -= TOP_LENGTH
59
60
    request.session['currentTopLength'] = current_top_length
61
    return HttpResponseRedirect(reverse('index'))
62
    
63
def decrement_current_toplength(request):
64
    current_top_length = request.session.get('currentTopLength', TOP_LENGTH)
65
    current_top_length -= TOP_LENGTH
66
67
    if current_top_length <= 0:
68
        current_top_length = TOP_LENGTH
69
70
    request.session['currentTopLength'] = current_top_length
71
    return HttpResponseRedirect(reverse('index'))
72
73
def _index_export(export, export_format, objects):
74
    counters = (
75
                ('all', {}),
76
                ('IDPSSO', {'types__xmlname': 'IDPSSODescriptor'}),
77
                ('SPSSO', {'types__xmlname': 'SPSSODescriptor'}),
78
               )
79
80
    if not export in ['interfederations', 'federations', 'most_federated_entities']:
81
        return HttpResponseBadRequest('Not valid export query')
82
83
    if export == 'most_federated_entities':
84
        return export_query_set(export_format, objects['most_federated_entities'],
85
                                'most_federated_entities', ('entityid', 'types', 'name', 'federations'))
86
    else:
87
        return export_summary(export_format, objects[export],
88
                              'entity_set', '%s_summary' % export,
89
                              counters)
90
91
@profile(name='Index page')
92
def index(request):
93
    ff = Federation.objects.all()
94
    federations = []
95
    interfederations = []
96
    for f in ff:
97
        if f.is_interfederation:
98
            interfederations.append(f)
99
        else:
100
            federations.append(f)
101
102
    cc = Entity.objects.values('federations__id', 'types__xmlname').annotate(Count('federations__id'), Count('types__xmlname'))
103
    counts = {}
104
    for curtype in DESCRIPTOR_TYPES:
105
        counts[curtype] = []
106
        for c in cc:
107
            if c['types__xmlname'] == curtype:
108
                counts[curtype].append(c)
109
    counts['All'] = Entity.objects.values('federations__id').annotate(Count('federations__id'))
110
111
    totals = Entity.objects.values('types__xmlname').annotate(Count('types__xmlname'))
112
113
    # Entities with count how many federations belongs to, and sorted by most first
114
    current_top_length = request.session.get('currentTopLength', TOP_LENGTH)
115
    most_federated_entities = Entity.get_most_federated_entities(maxlength=current_top_length, cache_expire=24*60*60)
116
117
    params = {
118
       'settings': settings,
119
       'interfederations': interfederations,
120
       'federations': federations,
121
       'entity_types': DESCRIPTOR_TYPES,
122
       'federation_path': request.path,
123
       'counts': counts,
124
       'totals': totals,
125
       'most_federated_entities': most_federated_entities,
126
    }
127
128
    export = request.GET.get('export', None)
129
    export_format = request.GET.get('format', None)
130
    if export and export_format:
131
        return _index_export(export, export_format, params)
132
    
133
    return render_to_response('metadataparser/index.html', params, context_instance=RequestContext(request))
134
135
def _paginate_fed(ob_entities, page):
136
    paginator = Paginator(ob_entities, 20)
137
138
    try:
139
        ob_entities = paginator.page(page)
140
    except PageNotAnInteger:
141
        ob_entities = paginator.page(1)
142
    except EmptyPage:
143
        ob_entities = paginator.page(paginator.num_pages)
144
145
    adjacent_pages = 5
146
    page_range = [n for n in \
147
                  range(ob_entities.number - adjacent_pages, ob_entities.number + adjacent_pages + 1) \
148
                  if n > 0 and n <= ob_entities.paginator.num_pages]
149
150
    return {
151
        'page_range': page_range,
152
        'cur_page_number': ob_entities.number,
153
        'num_pages': ob_entities.paginator.num_pages,
154
    }
155
156
@profile(name='Federation view')
157
def federation_view(request, federation_slug=None):
158
    if federation_slug:
159
        request.session['%s_process_done' % federation_slug] = False
160
        request.session['%s_num_entities' % federation_slug] = 0
161
        request.session['%s_cur_entities' % federation_slug] = 0
162
        request.session.save()
163
164
    federation = get_object_or_404(Federation, slug=federation_slug)
165
166
    entity_type = None
167
    if request.GET and 'entity_type' in request.GET:
168
        entity_type = request.GET['entity_type']
169
        ob_entities = Entity.objects.filter(federations__id=federation.id).filter(types__xmlname=entity_type)
170
    else:
171
        ob_entities = Entity.objects.filter(federations__id=federation.id)
172
    
173
    ob_entities = ob_entities.prefetch_related('types', 'federations')
174
    pagination = _paginate_fed(ob_entities, request.GET.get('page'))
175
176
    entities = []
177
    for entity in ob_entities:
178
        entities.append({
179
            'entityid': entity.entityid,
180
            'name': entity.name,
181
            'absolute_url': entity.get_absolute_url(),
182
            'types': [unicode(item) for item in entity.types.all()],
183
            'federations': [(unicode(item.name), item.get_absolute_url()) for item in entity.federations.all()],
184
        })
185
186
    if 'format' in request.GET:
187
        return export_query_set(request.GET.get('format'), entities,
188
                                'entities_search_result', ('entityid', 'types', 'federations'))
189
190
    context = RequestContext(request)
191
    user = context.get('user', None)
192
    add_entity = user and user.has_perm('metadataparser.add_federation')
193
    pie_chart = fed_pie_chart(request, federation.id)
194
195
    return render_to_response('metadataparser/federation_view.html',
196
            {'settings': settings,
197
             'federation': federation,
198
             'entity_types': DESCRIPTOR_TYPES,
199
             'entity_type': entity_type or 'All',
200
             'fed_types': dict(FEDERATION_TYPES),
201
             'entities': entities,
202
             'show_filters': True,
203
             'add_entity': add_entity,
204
             'lang': request.GET.get('lang', 'en'),
205
             'update_entities': request.GET.get('update', 'false'),
206
             'statcharts': [pie_chart],
207
             'pagination': pagination,
208
            }, context_instance=context)
209
210
211
@user_can_edit(Federation)
212
def federation_edit_post(request, federation, form):
213
    modify = True if federation else False
214
    form.save()
215
216
    if not modify:
217
        form.instance.editor_users.add(request.user)
218
    if 'file' in form.changed_data or 'file_url' in form.changed_data:
219
        form.instance.process_metadata()
220
        #form.instance.process_metadata_entities(request=request)
221
222
    messages.success(request, _('Federation %s successfully' % 'modified' if modify else 'created'))
223
    return HttpResponseRedirect(form.instance.get_absolute_url() + '?update=true')
224
225
226
@user_can_edit(Federation)
227
def federation_edit(request, federation_slug=None):
228
    federation = get_object_or_404(Federation, slug=federation_slug) if federation_slug else None
229
230
    if request.method == 'POST':
231
        form = FederationForm(request.POST, request.FILES, instance=federation)
232
        if not form.is_valid():
233
            messages.error(request, _('Please correct the errors indicated below'))
234
        else:
235
            return federation_edit_post(request, federation, form)
236
    else:
237
        form = FederationForm(instance=federation)
238
239
    context = RequestContext(request)
240
    user = context.get('user', None)
241
    delete_federation = user and user.has_perm('metadataparser.delete_federation')
242
    return render_to_response('metadataparser/federation_edit.html',
243
                              {'settings': settings, 'form': form, 'delete_federation': delete_federation},
244
                              context_instance=RequestContext(request))
245
246
247
@user_can_edit(Federation)
248
def federation_update_entities(request, federation_slug=None):
249
    federation = get_object_or_404(Federation, slug=federation_slug)
250
    federation.process_metadata_entities(request=request, federation_slug=federation_slug)
251
252
    messages.success(request, _('Federation entities updated succesfully'))
253
    return HttpResponse("Done. All entities updated.", content_type='text/plain')
254
255
256
def entityupdate_progress(request, federation_slug=None):
257
    data = { 'done': False }
258
    if federation_slug:
259
        data = { 'done': request.session.get('%s_process_done' % federation_slug, False),
260
                 'tot': request.session.get('%s_num_entities' % federation_slug, 0),
261
                 'num': request.session.get('%s_cur_entities' % federation_slug, 0) }
262
263
    return HttpResponse(json.dumps(data), content_type='application/javascript')
264
265
266
@user_can_edit(Federation, True)
267
def federation_delete(request, federation_slug):
268
    federation = get_object_or_404(Federation, slug=federation_slug)
269
270
    for entity in federation.entity_set.all():
271
        if len(entity.federations.all()) == 1:
272
            entity.delete()
273
274
    messages.success(request,
275
                     _(u"%(federation)s federation was deleted successfully"
276
                     % {'federation': unicode(federation)}))
277
    federation.delete()
278
    return HttpResponseRedirect(reverse('index'))
279
280
281
@profile(name='Index charts')
282
def federation_charts(request, federation_slug=None):
283
    if federation_slug is None:
284
        federation = None
285
    else:
286
        federation = get_object_or_404(Federation, slug=federation_slug)
287
288
    if request.method == 'POST':
289
        form = ChartForm(request.POST, request.FILES, instance=federation)
290
291
        if form.is_valid():
292
            stats_config_dict = getattr(settings, "STATS")
293
            service_terms = stats_config_dict['statistics']['entity_by_type']['terms']
294
            protocol_terms = stats_config_dict['statistics']['entity_by_protocol']['terms']
295
            
296
            protocols = stats_config_dict['protocols']
297
298
            from_time = datetime.fromordinal(form.cleaned_data['fromDate'].toordinal())
299
            if timezone.is_naive(from_time):
300
                from_time = pytz.utc.localize(from_time)
301
            to_time = datetime.fromordinal(form.cleaned_data['toDate'].toordinal() + 1)
302
            if timezone.is_naive(to_time):
303
                to_time = pytz.utc.localize(to_time)
304
305
            service_stats = EntityStat.objects.filter(  federation=federation \
306
                                              , feature__in = service_terms \
307
                                              , time__gte = from_time \
308
                                              , time__lte = to_time).order_by("time")
309
310
            protocol_stats = EntityStat.objects.filter(  federation=federation \
311
                                              , feature__in = protocol_terms \
312
                                              , time__gte = from_time \
313
                                              , time__lte = to_time).order_by("time")
314
315
            s_chart = stats_chart(stats_config_dict, request, service_stats, 'entity_by_type')
316
317
            p_chart = stats_chart(stats_config_dict, request, protocol_stats, 'entity_by_protocol', protocols)
318
319
            return render_to_response('metadataparser/federation_chart.html',
320
                                      {'form': form,
321
                                       'statcharts': [s_chart, p_chart],
322
                                      },
323
                                      context_instance=RequestContext(request))
324
325
        else:
326
            messages.error(request, _('Please correct the errors indicated'
327
                                      ' below'))
328
    else:
329
        form = ChartForm(instance=federation)
330
331
    return render_to_response('metadataparser/federation_chart.html',
332
                              {'settings': settings, 'form': form},
333
                              context_instance=RequestContext(request))
334
335
336
def stats_chart(stats_config_dict, request, stats, entity, protocols=None):
337
    
338
    terms = stats_config_dict['statistics'][entity]['terms']
339
    title = stats_config_dict['statistics'][entity]['title']
340
    x_title = stats_config_dict['statistics'][entity]['x_title']
341
    y_title = stats_config_dict['statistics'][entity]['y_title']
342
    chart_type = 'column'
343
    stacking = True
344
    term_names = stats_config_dict['feature_names']
345
    time_format = stats_config_dict['time_format']
346
347
    statdata = _create_statdata('bar', stats, terms, term_names)
348
    graph = 'protocols' if protocols else 'entities'
349
350
    series_options = []
351
    for stack in range(len(protocols) if protocols else 1):
352
        for term in terms:
353
            if not protocols or term.endswith(protocols[stack]):
354
                series_options += \
355
                  [{'options':{
356
                      'type': chart_type,
357
                      'stacking': stacking,
358
                      'stack': stack,
359
                    },
360
                    'terms':{
361
                      'time_%s' %term: [{term_names[term]: {'stack': stack, }}],
362
                    }}]
363
364
    chart_options = _get_chart_options('bar', title, x_title, y_title)
365
366
    return Chart(
367
        datasource = statdata,
368
        series_options = series_options,
369
        chart_options = chart_options, 
370
        x_sortf_mapf_mts=(None, lambda i: datetime.fromtimestamp(time.mktime(i.replace(tzinfo=tz.gettz('UTC')).astimezone(tz.tzlocal()).timetuple())).strftime(time_format), False)
371
    )
372
373
374
375
def _create_statdata(chart_type, stats, terms=None, term_names=None):
376
    if chart_type == 'bar':
377
        statdata = DataPool(
378
           series=[{'options': {
379
                       'source': stats.filter(feature=term)},
380
                       'legend_by': 'feature',
381
                       'terms': [{'time_%s' %term :'time'}, 
382
                                 {term_names[term] : 'value', 'name': 'feature'}]
383
                    } for term in terms]
384
        )
385
    elif chart_type == 'pie':
386
        statdata = DataPool(
387
           series=[{'options': { 'source': stats },
388
                    'legend_by': 'feature',
389
                    'terms': ['feature', 'value'],
390
                  }]
391
        )
392
    else:
393
        statdata = None
394
395
    return statdata
396
397
def _get_chart_options(chart_type, title=None, x_title=None, y_title=None):
398
    if chart_type == 'bar':
399
        chart_options = {'title': { 'text': title },
400
           'xAxis': {
401
                'title': { 'text': x_title },
402
                'labels': {
403
                   'rotation': -45,
404
                   'align': 'right'
405
                },
406
                'max': 10,
407
            },
408
           'yAxis': {
409
                'title': { 'text': y_title },
410
                'minorTickInterval': 'auto'
411
            },
412
           'credits': { 'enabled': False },
413
           'scrollbar': { 'enabled': True },
414
           'zoomType': 'xy',
415
        }
416
    elif chart_type == 'pie':
417
        chart_options = {
418
            'title': { 'text': ' ' },
419
            'credits': { 'enabled': False}
420
        }
421
    else:
422
        chart_options = None
423
424
    return chart_options
425
426
def fed_pie_chart(request, federation_id):
427
    stats_config_dict = getattr(settings, "STATS")
428
    terms = stats_config_dict['statistics']['entity_by_type']['terms']
429
    stats = EntityStat.objects.filter(federation = federation_id, \
430
                                      feature__in = terms).order_by('-time')[0:len(terms)]
431
    term_names = stats_config_dict['feature_names']
432
433
    statdata = _create_statdata('pie', stats)
434
    series_options = \
435
        [{'options': { 'type': 'pie', 'stacking': False, 'size': '70%' },
436
         'terms':{ 'feature': [ 'value' ] }}]
437
    chart_options = _get_chart_options('pie')
438
439
    return Chart(
440
        datasource = statdata,
441
        series_options = series_options,
442
        chart_options = chart_options,
443
    )
444
445
446
447
@profile(name='Entity view')
448
def entity_view(request, entityid):
449
    entityid = unquote(entityid)
450
    entityid = RESCUE_SLASH.sub("\\1/\\2", entityid)
451
452
    entity = get_object_or_404(Entity, entityid=entityid)
453
454
    if 'federation' in request.GET:
455
        federation = get_object_or_404(Federation, slug=request.GET.get('federation'))
456
        entity.curfed = federation
457
458
    if 'format' in request.GET:
459
        return export_entity(request.GET.get('format'), entity)
460
461
    if 'viewxml' in request.GET:
462
        serialized = entity.xml
463
        response = HttpResponse(serialized, content_type='application/xml')
464
        return response
465
466
    return render_to_response('metadataparser/entity_view.html',
467
            {'settings': settings,
468
             'entity': entity,
469
             'lang': request.GET.get('lang', 'en') 
470
            }, context_instance=RequestContext(request))
471
472
473
@user_can_edit(Entity)
474
def entity_edit_post(request, form, federation, entity):
475
    form.save()
476
    if federation and not federation in form.instance.federations.all():
477
        form.instance.federations.add(federation)
478
        form.instance.save()
479
480
    if entity:
481
        messages.success(request, _('Entity modified successfully'))
482
    else:
483
        messages.success(request, _('Entity created successfully'))
484
485
    return HttpResponseRedirect(form.instance.get_absolute_url())
486
487
488
489
@user_can_edit(Entity)
490
def entity_edit(request, federation_slug=None, entity_id=None):
491
    entity = None
492
    federation = None
493
    if federation_slug:
494
        federation = get_object_or_404(Federation, slug=federation_slug)
495
        if entity_id:
496
            entity = get_object_or_404(Entity, id=entity_id,
497
                                       federations__id=federation.id)
498
    if entity_id and not federation_slug:
499
        entity = get_object_or_404(Entity, id=entity_id)
500
501
    if request.method == 'POST':
502
        form = EntityForm(request.POST, request.FILES, instance=entity)
503
        if form.is_valid():
504
            return entity_edit_post(request, form, federation, entity)
505
        else:
506
            messages.error(request, _('Please correct the errors indicated below'))
507
    else:
508
        form = EntityForm(instance=entity)
509
510
    return render_to_response('metadataparser/entity_edit.html',
511
                              {'settings': settings,
512
                               'form': form,
513
                               'federation': federation},
514
                              context_instance=RequestContext(request))
515
516
517
@user_can_edit(Entity, True)
518
def entity_delete(request, entity_id):
519
    entity = get_object_or_404(Entity, id=entity_id)
520
    messages.success(request,
521
                     _(u"%(entity)s entity was deleted successfully"
522
                     % {'entity': unicode(entity)}))
523
    entity.delete()
524
    return HttpResponseRedirect(reverse('index'))
525
526
527
def entity_comment(request, federation_slug=None, entity_id=None):
528
    entity = None
529
    federation = None
530
    if federation_slug:
531
        federation = get_object_or_404(Federation, slug=federation_slug)
532
        if entity_id:
533
            entity = get_object_or_404(Entity, id=entity_id,
534
                                       federations__id=federation.id)
535
    if entity_id and not federation_slug:
536
        entity = get_object_or_404(Entity, id=entity_id)
537
538
    if request.method == 'POST':
539
        form = EntityCommentForm(request.POST, request.FILES, instance=entity)
540
        if form.is_valid():
541
            mail_config = getattr(settings, "MAIL_CONFIG")
542
            try:
543
                subject = mail_config['comment_subject'] %entity
544
                send_mail(form.data['email'], subject, form.data['comment'])
545
                messages.success(request, _('Comment posted successfully'))
546
            except Exception, errorMessage:
547
                messages.error(request, _('Comment could not be posted successfully: %s' %errorMessage))
548
549
            return HttpResponseRedirect(form.instance.get_absolute_url())
550
551
        else:
552
            messages.error(request, _('Please correct the errors indicated'
553
                                      ' below'))
554
    else:
555
        form = EntityCommentForm(instance=entity)
556
557
    return render_to_response('metadataparser/entity_comment.html',
558
                              {'settings': settings,
559
                               'form': form,
560
                              },
561
                              context_instance=RequestContext(request))
562
563
564
def entity_proposal(request, federation_slug=None, entity_id=None):
565
    entity = None
566
    federation = None
567
    if federation_slug:
568
        federation = get_object_or_404(Federation, slug=federation_slug)
569
        if entity_id:
570
            entity = get_object_or_404(Entity, id=entity_id,
571
                                       federations__id=federation.id)
572
    if entity_id and not federation_slug:
573
        entity = get_object_or_404(Entity, id=entity_id)
574
575
    if request.method == 'POST':
576
        form = EntityProposalForm(request.POST, request.FILES, instance=entity)
577
     
578
        if form.is_valid():
579
            mail_config = getattr(settings, "MAIL_CONFIG")
580
            try:
581
                subject = mail_config['proposal_subject'] %entity
582
                my_dict = dict(form.data.iterlists())
583
                body = mail_config['proposal_body'] % (entity, ', '.join(my_dict['federations']), form.data['comment'])
584
                send_mail(form.data['email'], subject, body)
585
                messages.success(request, _('Proposal posted successfully'))
586
            except Exception, errorMessage:
587
                messages.error(request, _('Proposal could not be posted successfully: %s' %errorMessage))
588
589
            return HttpResponseRedirect(form.instance.get_absolute_url())
590
591
        else:
592
            messages.error(request, _('Please correct the errors indicated'
593
                                      ' below'))
594
    else:
595
        form = EntityProposalForm(instance=entity)
596
597
    return render_to_response('metadataparser/entity_proposal.html',
598
                              {'settings': settings,
599
                               'form': form,
600
                              },
601
                              context_instance=RequestContext(request))
602
603
def search_service(request):
604
    filters = {}
605
    objects = []
606
607
    if 'entityid' in request.GET:
608
        form = ServiceSearchForm(request.GET)
609
        if form.is_valid():
610
            entityid = form.cleaned_data['entityid']
611
            entityid = entityid.strip()
612
            filters['entityid__icontains'] = entityid
613
    else:
614
        form = ServiceSearchForm()
615
    entity_type = request.GET.get('entity_type', None)
616
617
    if entity_type:
618
        filters['entity_type'] = entity_type
619
620
    if filters:
621
        objects = Entity.objects.filter(**filters)
622
623
    if objects and 'format' in request.GET.keys():
624
        return export_query_set(request.GET.get('format'), objects,
625
                                'entities_search_result', ('entityid', 'types', 'federations'))
626
627
    entities = []
628
    for entity in objects:
629
        entities.append({
630
            'entityid': entity.entityid,
631
            'name': entity.name,
632
            'absolute_url': entity.get_absolute_url(),
633
            'types': [unicode(item) for item in entity.types.all()],
634
            'federations': [(unicode(item.name), item.get_absolute_url()) for item in entity.federations.all()],
635
        })
636
637
    return render_to_response('metadataparser/service_search.html',
638
        {'settings': settings,
639
         'searchform': form,
640
         'object_list': entities,
641
         'show_filters': False,
642
        }, context_instance=RequestContext(request))
643
644
def met_logout(request):
645
    logout(request)
646
    return HttpResponseRedirect(request.GET.get("next", "/"))
647