def fares_available(context, fare_type, sort=None): """ Restituisce l'elenco delle tariffe attive in questo momento per la tipologia specificata. """ assert fare_type in ('all', 'conference', 'goodies', 'partner', 'hotel-room', 'hotel-room-sharing', 'other') if not settings.P3_FARES_ENABLED(context['user']): return [] fares_list = filter(lambda f: f['valid'], cdataaccess.fares(settings.CONFERENCE_CONFERENCE)) if fare_type == 'conference': fares = [ f for f in fares_list if f['code'][0] == 'T' and f['ticket_type'] == 'conference' ] elif fare_type == 'hotel-room-sharing': fares = [ f for f in fares_list if f['code'].startswith('HB') ] elif fare_type == 'hotel-room': fares = [ f for f in fares_list if f['code'].startswith('HR') ] elif fare_type == 'other': fares = [ f for f in fares_list if f['ticket_type'] in ('other', 'event') and f['code'][0] != 'H' ] elif fare_type == 'partner': fares = [ f for f in fares_list if f['ticket_type'] in 'partner' ] elif fare_type == 'all': fares = fares_list if sort == "price": fares.sort(key=lambda x: x['price']) return fares
def fares_available(context, fare_type, sort=None): """ Restituisce l'elenco delle tariffe attive in questo momento per la tipologia specificata. """ assert fare_type in ('all', 'conference', 'goodies', 'partner', 'hotel-room', 'hotel-room-sharing', 'other') if not settings.P3_FARES_ENABLED(context['user']): return [] fares_list = filter(lambda f: f['valid'], cdataaccess.fares(settings.CONFERENCE_CONFERENCE)) if fare_type == 'conference': fares = [ f for f in fares_list if f['code'][0] == 'T' and f['ticket_type'] == 'conference' ] elif fare_type == 'hotel-room-sharing': fares = [ f for f in fares_list if f['code'].startswith('HB') ] elif fare_type == 'hotel-room': fares = [ f for f in fares_list if f['code'].startswith('HR') ] elif fare_type == 'other': fares = [ f for f in fares_list if f['ticket_type'] in ('other', 'event') and f['code'][0] != 'H' ] elif fare_type == 'partner': fares = [ f for f in fares_list if f['ticket_type'] in 'partner' ] elif fare_type == 'all': fares = fares_list if sort == "price": fares.sort(key=lambda x: x['price']) return fares
def my_schedule(request, conference): qs = cmodels.Event.objects\ .filter(eventinterest__user=request.user, eventinterest__interest__gt=0)\ .filter(schedule__conference=conference)\ .values('id', 'schedule') events = defaultdict(list) for x in qs: events[x['schedule']].append(x['id']) qs = cmodels.EventBooking.objects\ .filter(user=request.user, event__schedule__conference=conference)\ .values('event', 'event__schedule') for x in qs: events[x['event__schedule']].append(x['event']) qs = cmodels.Ticket.objects\ .filter(user=request.user)\ .filter(fare__conference=conference, fare__ticket_type='partner')\ .values_list('fare', flat=True) from conference.dataaccess import fares, schedules_data pfares = [f for f in fares(conference) if f['id'] in qs] partner = _partner_as_event(pfares) schedules = schedules_data(events.keys()) tts = _build_timetables(schedules, events=events, partner=partner) ctx = { 'conference': conference, 'sids': [x[0] for x in tts], 'timetables': tts, } return render(request, 'p3/my_schedule.html', ctx)
def my_schedule(request, conference): qs = cmodels.Event.objects\ .filter(eventinterest__user=request.user, eventinterest__interest__gt=0)\ .filter(schedule__conference=conference)\ .values('id', 'schedule') events = defaultdict(list) for x in qs: events[x['schedule']].append(x['id']) qs = cmodels.EventBooking.objects\ .filter(user=request.user, event__schedule__conference=conference)\ .values('event', 'event__schedule') for x in qs: events[x['event__schedule']].append(x['event']) qs = cmodels.Ticket.objects\ .filter(user=request.user)\ .filter(fare__conference=conference, fare__ticket_type='partner')\ .values_list('fare', flat=True) from conference.dataaccess import fares, schedules_data pfares = [ f for f in fares(conference) if f['id'] in qs ] partner = _partner_as_event(pfares) schedules = schedules_data(events.keys()) tts = _build_timetables(schedules, events=events, partner=partner) ctx = { 'conference': conference, 'sids': [ x[0] for x in tts ], 'timetables': tts, } return render(request, 'p3/my_schedule.html', ctx)
def _conference_timetables(conference): """ Return the TimeTable about the conference.""" # The timetables must contain both events in the db and "artificial" # events from partner program sids = cmodels.Schedule.objects\ .filter(conference=conference)\ .values_list('id', flat=True) from conference.dataaccess import fares, schedules_data pfares = [f for f in fares(conference) if f['ticket_type'] == 'partner'] partner = _partner_as_event(pfares) schedules = schedules_data(sids) tts = _build_timetables(schedules, partner=partner) return tts
def _conference_timetables(conference): """ Restituisce le TimeTable relative alla conferenza. """ # Le timetable devono contenere sia gli eventi presenti nel db sia degli # eventi "artificiali" del partner program sids = cmodels.Schedule.objects\ .filter(conference=conference)\ .values_list('id', flat=True) from conference.dataaccess import fares, schedules_data pfares = [ f for f in fares(conference) if f['ticket_type'] == 'partner' ] partner = _partner_as_event(pfares) schedules = schedules_data(sids) tts = _build_timetables(schedules, partner=partner) return tts
def _conference_timetables(conference): """ Restituisce le TimeTable relative alla conferenza. """ # Le timetable devono contenere sia gli eventi presenti nel db sia degli # eventi "artificiali" del partner program sids = cmodels.Schedule.objects\ .filter(conference=conference)\ .values_list('id', flat=True) from conference.dataaccess import fares, schedules_data pfares = [f for f in fares(conference) if f['ticket_type'] == 'partner'] partner = _partner_as_event(pfares) schedules = schedules_data(sids) tts = _build_timetables(schedules, partner=partner) return tts
def _conference_timetables(conference): """ Restituisce le TimeTable relative alla conferenza. """ # The timetables must contain both events in the db and "artificial" # events from partner program sids = cmodels.Schedule.objects\ .filter(conference=conference)\ .values_list('id', flat=True) from conference.dataaccess import fares, schedules_data pfares = [ f for f in fares(conference) if f['ticket_type'] == 'partner' ] partner = _partner_as_event(pfares) schedules = schedules_data(sids) tts = _build_timetables(schedules, partner=partner) return tts
def render(self, name, value, attrs=None): start = self.booking.booking_start from django.template.loader import render_to_string from conference import dataaccess as cdataaccess tpl = 'p3/fragments/form_field_hotel_reservation_widget.html' fares = { 'HR': [], 'HB': [], } for f in cdataaccess.fares(settings.CONFERENCE_CONFERENCE): if not f['valid']: continue if f['code'][:2] == 'HR': fares['HR'].append(f) elif f['code'][:2] == 'HB': fares['HB'].append(f) if not fares['HR'] and not fares['HB']: return '' if not value: value = [] if fares['HB']: value.append({ 'fare': fares['HB'][0]['code'], 'qty': 0, 'period': (self.booking.default_start, self.booking.default_end), }) if fares['HR']: value.append({ 'fare': fares['HR'][0]['code'], 'qty': 0, 'period': (self.booking.default_start, self.booking.default_end), }) types = getattr(self, 'types', ['HR', 'HB']) rows = [] for entry in value: k = entry['fare'][:2] if k not in ('HR', 'HB'): raise TypeError('unsupported fare') if k not in types: continue ctx = { 'label': '', 'type': '', 'qty': entry['qty'], 'period': map(lambda x: (x - start).days, entry['period']), 'fare': entry['fare'], 'fares': [], 'minimum_night': self.booking.minimum_night, } if k == 'HB': ctx['label'] = _('Room sharing') ctx['type'] = 'bed' ctx['fares'] = fares['HB'] else: ctx['label'] = _('Full room') ctx['type'] = 'room' ctx['fares'] = fares['HR'] rows.append(ctx) # XXX crappy hack! # given the way I've implemented widget rendering I need to # know here and now if there are errors, to be able to show # them in the correct position. # Unfortunately the errors are a property of BoundField, not # of Field or of the widget. # This bad hack works just because in the templatetag I'm # connecting to the widget the errors of the form. # The clean way would be instead reimplementing the rendering # of subwidget as it's done for RadioInput, passing from # filter |field and inserting the error at that point. errors = [None] * len(rows) if hasattr(self, '_errors'): print self._errors for e in self._errors: try: ix, msg = e.split(':', 1) except ValueError: continue try: errors[int(ix)] = msg except: continue for e in zip(rows, errors): if e[1]: e[0]['error'] = e[1] ctx = { 'start': start, 'days': (self.booking.booking_end - start).days, 'rows': rows, 'name': name, } return render_to_string(tpl, ctx)
def render_cart_rows(context, fare_type, form): assert fare_type in ('conference', 'goodies', 'partner', 'hotel-room', 'hotel-room-sharing', 'other') ctx = Context(context) request = ctx['request'] try: company = request.user.assopy_user.account_type == 'c' except AttributeError: # anonymous user or without an assopy profile (impossible!) company = False ctx.update({ 'form': form, 'company': company, }) fares_list = filter(lambda f: f['valid'], cdataaccess.fares(settings.CONFERENCE_CONFERENCE)) if fare_type == 'conference': tpl = 'p3/fragments/render_cart_conference_ticket_row.html' # rendering "conference" tickets is a bit complex; each row in # the cart corresponds to multiple "fare" (student, private, copany) # # The prices must be sorted on time + ticket type + owner # early # full [Student, Private, Company] # lite (standard) [Student, Private, Company] # daily [Student, Private, Company] # regular (late) # ... # on desk # ... # # The correct time ordering is guaranteed implicitly by # excluding expired fares (it's not permitted to have overlaps # of validity periods). # # Ticket code conventions: # - all ticket codes must start with 'T' # - second letter stands for ticket type: # 'E' - early bird # 'R' - normal # 'D' - on-desk # - third letter: ticket variant # 'S' - standard # 'L' - standard light (without trainings) # 'D' - day pass # 'T' - training pass # - fourth letter: group type # 'S' - student # 'P' - personal # 'C' - company # fares = dict((f['code'][2:], f) for f in fares_list if f['code'][0] == 'T') rows = [] for t in ('S', 'L', 'D', 'T'): # To simplify the template fares are packed in triplets: # student, private, company. # # Each row is a tuple with three elements: # 1. Fare # 2. FormField # 3. Boolean flag telling if the price can be applied to the user row = [] for k in ('S', 'P', 'C'): try: f = fares[t+k] except KeyError: row.append((None, None, None)) else: # The price is valid if the time test is passed and if the # account type is compatible valid = not (company ^ (f['code'][-1] == 'C')) row.append((f, form.__getitem__(f['code']), valid)) rows.append(row) ctx['rows'] = rows elif fare_type == 'hotel-room-sharing': tpl = 'p3/fragments/render_cart_hotel_ticket_row.html' ctx['field'] = form['bed_reservations'] ctx['field'].field.widget._errors = ctx['field'].errors elif fare_type == 'hotel-room': tpl = 'p3/fragments/render_cart_hotel_ticket_row.html' ctx['field'] = form['room_reservations'] ctx['field'].field.widget._errors = ctx['field'].errors elif fare_type == 'other': tpl = 'p3/fragments/render_cart_og_ticket_row.html' fares = defaultdict(dict) order = ('p', 'c') columns = set() for f in fares_list: if f['ticket_type'] in ('other', 'event') and f['code'][0] != 'H': columns.add(f['recipient_type']) fares[f['name']][f['recipient_type']] = f ctx['fares'] = fares.values() ctx['recipient_types'] = sorted(columns, key=lambda v: order.index(v)) elif fare_type == 'partner': tpl = 'p3/fragments/render_cart_partner_ticket_row.html' ctx['fares'] = [ f for f in fares_list if f['ticket_type'] in 'partner' ] return render_to_string(tpl, ctx)
def render(self, name, value, attrs=None): start = self.booking.booking_start from django.template.loader import render_to_string from conference import dataaccess as cdataaccess tpl = 'p3/fragments/form_field_hotel_reservation_widget.html' fares = { 'HR': [], 'HB': [], } for f in cdataaccess.fares(settings.CONFERENCE_CONFERENCE): if not f['valid']: continue if f['code'][:2] == 'HR': fares['HR'].append(f) elif f['code'][:2] == 'HB': fares['HB'].append(f) if not fares['HR'] and not fares['HB']: return '' if not value: value = [] if fares['HB']: value.append({ 'fare': fares['HB'][0]['code'], 'qty': 0, 'period': (self.booking.default_start, self.booking.default_end), }) if fares['HR']: value.append({ 'fare': fares['HR'][0]['code'], 'qty': 0, 'period': (self.booking.default_start, self.booking.default_end), }) types = getattr(self, 'types', ['HR', 'HB']) rows = [] for entry in value: k = entry['fare'][:2] if k not in ('HR', 'HB'): raise TypeError('unsupported fare') if k not in types: continue ctx = { 'label': '', 'type': '', 'qty': entry['qty'], 'period': map(lambda x: (x-start).days, entry['period']), 'fare': entry['fare'], 'fares': [], 'minimum_night': self.booking.minimum_night, } if k == 'HB': ctx['label'] = _('Room sharing') ctx['type'] = 'bed' ctx['fares'] = fares['HB'] else: ctx['label'] = _('Full room') ctx['type'] = 'room' ctx['fares'] = fares['HR'] rows.append(ctx) # XXX crappy hack! # given the way I've implemented widget rendering I need to # know here and now if there are errors, to be able to show # them in the correct position. # Unfortunately the errors are a property of BoundField, not # of Field or of the widget. # This bad hack works just because in the templatetag I'm # connecting to the widget the errors of the form. # The clean way would be instead reimplementing the rendering # of subwidget as it's done for RadioInput, passing from # filter |field and inserting the error at that point. errors = [None] * len(rows) if hasattr(self, '_errors'): print self._errors for e in self._errors: try: ix, msg = e.split(':', 1) except ValueError: continue try: errors[int(ix)] = msg except: continue for e in zip(rows, errors): if e[1]: e[0]['error'] = e[1] ctx = { 'start': start, 'days': (self.booking.booking_end-start).days, 'rows': rows, 'name': name, } return render_to_string(tpl, ctx)
def render_cart_rows(context, fare_type, form): assert fare_type in ('conference', 'goodies', 'partner', 'hotel-room', 'hotel-room-sharing', 'other') ctx = Context(context) request = ctx['request'] try: company = request.user.assopy_user.account_type == 'c' except AttributeError: # anonymous user or without an assopy profile (impossible!) company = False ctx.update({ 'form': form, 'company': company, }) fares_list = filter(lambda f: f['valid'], cdataaccess.fares(settings.CONFERENCE_CONFERENCE)) if fare_type == 'conference': tpl = 'p3/fragments/render_cart_conference_ticket_row.html' # rendering "conference" tickets is a bit complex; each row in # the cart corresponds to multiple "fare" (student, private, copany) # # The prices must be sorted on time + ticket type + owner # early # full [Student, Private, Company] # lite (standard) [Student, Private, Company] # daily [Student, Private, Company] # regular (late) # ... # on desk # ... # # The correct time ordering is guaranteed implicitly by # excluding expired fares (it's not permitted to have overlaps # of validity periods). fares = dict((f['code'][2:], f) for f in fares_list if f['code'][0] == 'T') rows = [] for t in ('S', 'L', 'D'): # To simplify the template fares are packed in triplets: # student, private, company. # # Each raw is a tuple with three elements: # 1. Fare # 2. FormField # 3. Boolean flag telling if the price can be applied to the user row = [] for k in ('S', 'P', 'C'): try: f = fares[t+k] except KeyError: row.append((None, None, None)) else: # The price is valid if the time test is passed and if the # account type is compatible valid = not (company ^ (f['code'][-1] == 'C')) row.append((f, form.__getitem__(f['code']), valid)) rows.append(row) ctx['rows'] = rows elif fare_type == 'hotel-room-sharing': tpl = 'p3/fragments/render_cart_hotel_ticket_row.html' ctx['field'] = form['bed_reservations'] ctx['field'].field.widget._errors = ctx['field'].errors elif fare_type == 'hotel-room': tpl = 'p3/fragments/render_cart_hotel_ticket_row.html' ctx['field'] = form['room_reservations'] ctx['field'].field.widget._errors = ctx['field'].errors elif fare_type == 'other': tpl = 'p3/fragments/render_cart_og_ticket_row.html' fares = defaultdict(dict) order = ('p', 'c') columns = set() for f in fares_list: if f['ticket_type'] in ('other', 'event') and f['code'][0] != 'H': columns.add(f['recipient_type']) fares[f['name']][f['recipient_type']] = f ctx['fares'] = fares.values() ctx['recipient_types'] = sorted(columns, key=lambda v: order.index(v)) elif fare_type == 'partner': tpl = 'p3/fragments/render_cart_partner_ticket_row.html' ctx['fares'] = [ f for f in fares_list if f['ticket_type'] in 'partner' ] return render_to_string(tpl, ctx)
def render(self, name, value, attrs=None): try: start = settings.P3_HOTEL_RESERVATION['period'][0] except: raise TypeError('P3_HOTEL_RESERVATION not set') from django.template.loader import render_to_string from conference import dataaccess as cdataaccess tpl = 'p3/fragments/form_field_hotel_reservation_widget.html' fares = { 'HR': [], 'HB': [], } for f in cdataaccess.fares(settings.CONFERENCE_CONFERENCE): if not f['valid']: continue if f['code'][:2] == 'HR': fares['HR'].append(f) elif f['code'][:2] == 'HB': fares['HB'].append(f) if not fares['HR'] or not fares['HB']: return '' if not value: value = [ {'fare': fares['HB'][0]['code'], 'qty': 0, 'period': settings.P3_HOTEL_RESERVATION['default']}, {'fare': fares['HR'][0]['code'], 'qty': 0, 'period': settings.P3_HOTEL_RESERVATION['default']}, ] types = getattr(self, 'types', ['HR', 'HB']) rows = [] for entry in value: k = entry['fare'][:2] if k not in ('HR', 'HB'): raise TypeError('unsupported fare') if k not in types: continue ctx = { 'label': '', 'type': '', 'qty': entry['qty'], 'period': map(lambda x: (x-start).days, entry['period']), 'fare': entry['fare'], 'fares': [], } if k == 'HB': ctx['label'] = _('Room sharing') ctx['type'] = 'bed' ctx['fares'] = fares['HB'] else: ctx['label'] = _('Full room') ctx['type'] = 'room' ctx['fares'] = fares['HR'] rows.append(ctx) # XXX schifezza! # per come ho implementato il rendering del widget ho bisogno di sapere # qui e adesso se ci sono errori per mostrarli nel posto giusto. # Purtroppo gli errori sono una proprietà del BoundField non del field # ne tantomeno del widget. Questo codice è un accrocchio funziona # perché nel templatetag aggancio al widget gli errori della form. Il # modo pulito sarebbe implementare il rendering dei subwidget come # avviene per il RadioInput, passare dal filtro |field e inserire li # gli errori. errors = [None] * len(rows) if hasattr(self, '_errors'): print self._errors for e in self._errors: try: ix, msg = e.split(':', 1) except ValueError: continue try: errors[int(ix)] = msg except: continue for e in zip(rows, errors): if e[1]: e[0]['error'] = e[1] ctx = { 'start': start, 'days': (settings.P3_HOTEL_RESERVATION['period'][1]-start).days, 'rows': rows, 'name': name, } return render_to_string(tpl, ctx)
def render_cart_rows(context, fare_type, form): assert fare_type in ('conference', 'goodies', 'partner', 'hotel-room', 'hotel-room-sharing', 'other') ctx = Context(context) request = ctx['request'] try: company = request.user.assopy_user.account_type == 'c' except AttributeError: # utente anonimo o senza il profilo assopy (impossibile!) company = False ctx.update({ 'form': form, 'company': company, }) fares_list = filter(lambda f: f['valid'], cdataaccess.fares(settings.CONFERENCE_CONFERENCE)) if fare_type == 'conference': tpl = 'p3/fragments/render_cart_conference_ticket_row.html' # il rendering dei biglietti "conference" è un po' particolare, ogni # riga del carrello corrisponde a più `fare` (student, private, # company) # Le tariffe devono essere ordinate secondo l'ordine temporale + il # tipo di biglietto + il destinatario: # early # full [Student, Private, Company] # lite (standard) [Student, Private, Company] # daily [Student, Private, Company] # regular (late) # ... # on desk # ... # # L'ordine temporale viene implicitamente garantito dall'aver escluso # le fare non più valide (non permettiamo overlap nel range di # validità) fares = dict((f['code'][2:], f) for f in fares_list if f['code'][0] == 'T') rows = [] for t in ('S', 'L', 'D'): # Per semplificare il template impacchetto le fare a gruppi di tre: # studente, privato, azienda. # Ogni riha è una tupla con 3 elementi: # 1. Fare # 2. FormField # 3. Boolean che indica se la tariffa è utilizzabile dall'utente row = [] for k in ('S', 'P', 'C'): try: f = fares[t+k] except KeyError: row.append((None, None, None)) else: # la tariffa è valida se passa il controllo temporale e se il tipo # dell'account è compatibile valid = not (company ^ (f['code'][-1] == 'C')) row.append((f, form.__getitem__(f['code']), valid)) rows.append(row) ctx['rows'] = rows elif fare_type == 'hotel-room-sharing': tpl = 'p3/fragments/render_cart_hotel_ticket_row.html' ctx['field'] = form['bed_reservations'] ctx['field'].field.widget._errors = ctx['field'].errors elif fare_type == 'hotel-room': tpl = 'p3/fragments/render_cart_hotel_ticket_row.html' ctx['field'] = form['room_reservations'] ctx['field'].field.widget._errors = ctx['field'].errors elif fare_type == 'other': tpl = 'p3/fragments/render_cart_og_ticket_row.html' fares = defaultdict(dict) order = ('p', 'c') columns = set() for f in fares_list: if f['ticket_type'] in ('other', 'event') and f['code'][0] != 'H': columns.add(f['recipient_type']) fares[f['name']][f['recipient_type']] = f ctx['fares'] = fares.values() ctx['recipient_types'] = sorted(columns, key=lambda v: order.index(v)) elif fare_type == 'partner': tpl = 'p3/fragments/render_cart_partner_ticket_row.html' ctx['fares'] = [ f for f in fares_list if f['ticket_type'] in 'partner' ] return render_to_string(tpl, ctx)
def render_cart_rows(context, fare_type, form): assert fare_type in ('conference', 'goodies', 'partner', 'hotel-room', 'hotel-room-sharing', 'other') ctx = Context(context) request = ctx['request'] try: company = request.user.assopy_user.account_type == 'c' except AttributeError: # utente anonimo o senza il profilo assopy (impossibile!) company = False ctx.update({ 'form': form, 'company': company, }) fares_list = filter(lambda f: f['valid'], cdataaccess.fares(settings.CONFERENCE_CONFERENCE)) if fare_type == 'conference': tpl = 'p3/fragments/render_cart_conference_ticket_row.html' # il rendering dei biglietti "conference" è un po' particolare, ogni # riga del carrello corrisponde a più `fare` (student, private, # company) # Le tariffe devono essere ordinate secondo l'ordine temporale + il # tipo di biglietto + il destinatario: # early # full [Student, Private, Company] # lite (standard) [Student, Private, Company] # daily [Student, Private, Company] # regular (late) # ... # on desk # ... # # L'ordine temporale viene implicitamente garantito dall'aver escluso # le fare non più valide (non permettiamo overlap nel range di # validità) fares = dict( (f['code'][2:], f) for f in fares_list if f['code'][0] == 'T') rows = [] for t in ('S', 'L', 'D'): # Per semplificare il template impacchetto le fare a gruppi di tre: # studente, privato, azienda. # Ogni riha è una tupla con 3 elementi: # 1. Fare # 2. FormField # 3. Boolean che indica se la tariffa è utilizzabile dall'utente row = [] for k in ('S', 'P', 'C'): try: f = fares[t + k] except KeyError: row.append((None, None, None)) else: # la tariffa è valida se passa il controllo temporale e se il tipo # dell'account è compatibile valid = not (company ^ (f['code'][-1] == 'C')) row.append((f, form.__getitem__(f['code']), valid)) rows.append(row) ctx['rows'] = rows elif fare_type == 'hotel-room-sharing': tpl = 'p3/fragments/render_cart_hotel_ticket_row.html' ctx['field'] = form['bed_reservations'] ctx['field'].field.widget._errors = ctx['field'].errors elif fare_type == 'hotel-room': tpl = 'p3/fragments/render_cart_hotel_ticket_row.html' ctx['field'] = form['room_reservations'] ctx['field'].field.widget._errors = ctx['field'].errors elif fare_type == 'other': tpl = 'p3/fragments/render_cart_og_ticket_row.html' fares = defaultdict(dict) order = ('p', 'c') columns = set() for f in fares_list: if f['ticket_type'] in ('other', 'event') and f['code'][0] != 'H': columns.add(f['recipient_type']) fares[f['name']][f['recipient_type']] = f ctx['fares'] = fares.values() ctx['recipient_types'] = sorted(columns, key=lambda v: order.index(v)) elif fare_type == 'partner': tpl = 'p3/fragments/render_cart_partner_ticket_row.html' ctx['fares'] = [f for f in fares_list if f['ticket_type'] in 'partner'] return render_to_string(tpl, ctx)
def render(self, name, value, attrs=None): try: start = settings.P3_HOTEL_RESERVATION['period'][0] except: raise TypeError('P3_HOTEL_RESERVATION not set') from django.template.loader import render_to_string from conference import dataaccess as cdataaccess tpl = 'p3/fragments/form_field_hotel_reservation_widget.html' fares = { 'HR': [], 'HB': [], } for f in cdataaccess.fares(settings.CONFERENCE_CONFERENCE): if not f['valid']: continue if f['code'][:2] == 'HR': fares['HR'].append(f) elif f['code'][:2] == 'HB': fares['HB'].append(f) if not fares['HR'] or not fares['HB']: return '' if not value: value = [ { 'fare': fares['HB'][0]['code'], 'qty': 0, 'period': settings.P3_HOTEL_RESERVATION['default'] }, { 'fare': fares['HR'][0]['code'], 'qty': 0, 'period': settings.P3_HOTEL_RESERVATION['default'] }, ] types = getattr(self, 'types', ['HR', 'HB']) rows = [] for entry in value: k = entry['fare'][:2] if k not in ('HR', 'HB'): raise TypeError('unsupported fare') if k not in types: continue ctx = { 'label': '', 'type': '', 'qty': entry['qty'], 'period': map(lambda x: (x - start).days, entry['period']), 'fare': entry['fare'], 'fares': [], } if k == 'HB': ctx['label'] = _('Room sharing') ctx['type'] = 'bed' ctx['fares'] = fares['HB'] else: ctx['label'] = _('Full room') ctx['type'] = 'room' ctx['fares'] = fares['HR'] rows.append(ctx) # XXX schifezza! # per come ho implementato il rendering del widget ho bisogno di sapere # qui e adesso se ci sono errori per mostrarli nel posto giusto. # Purtroppo gli errori sono una proprietà del BoundField non del field # ne tantomeno del widget. Questo codice è un accrocchio funziona # perché nel templatetag aggancio al widget gli errori della form. Il # modo pulito sarebbe implementare il rendering dei subwidget come # avviene per il RadioInput, passare dal filtro |field e inserire li # gli errori. errors = [None] * len(rows) if hasattr(self, '_errors'): print self._errors for e in self._errors: try: ix, msg = e.split(':', 1) except ValueError: continue try: errors[int(ix)] = msg except: continue for e in zip(rows, errors): if e[1]: e[0]['error'] = e[1] ctx = { 'start': start, 'days': (settings.P3_HOTEL_RESERVATION['period'][1] - start).days, 'rows': rows, 'name': name, } return render_to_string(tpl, ctx)