docs: def form_valid(self,form):
          '''
          If the form is valid, pass its contents on to the next view.  In order to permit the registration
          form to be overridden flexibly, but without permitting storage of arbitrary data keys that could
          lead to potential security issues, a form class for this view can optionally specify a list of
          keys that are permitted.  If no such list is specified as instance.permitted_event_keys, then
          the default list are used.
          '''
          regSession = self.request.session.get(REG_VALIDATION_STR, {})
  
          # The session expires after a period of inactivity that is specified in preferences.
          expiry = timezone.now() + timedelta(minutes=getConstant('registration__sessionExpiryMinutes'))
          permitted_keys = getattr(form,'permitted_event_keys',['role',])
  
          try:
              event_listing = {
                  int(key.split("_")[-1]): {k:v for k,v in json.loads(value[0]).items() if k in permitted_keys}
                  for key,value in form.cleaned_data.items() if 'event' in key and value
              }
              non_event_listing = {key: value for key,value in form.cleaned_data.items() if 'event' not in key}
          except (ValueError, TypeError) as e:
              form.add_error(None,ValidationError(_('Invalid event information passed.'),code='invalid'))
              return super(ClassRegistrationView,self).form_invalid(form)
  
          associated_events = Event.objects.filter(id__in=[k for k in event_listing.keys()])
  
          # Include the submission user if the user is authenticated
          if self.request.user.is_authenticated:
              submissionUser = self.request.user
          else:
              submissionUser = None
  
          reg = TemporaryRegistration(
              submissionUser=submissionUser,dateTime=timezone.now(),
              payAtDoor=non_event_listing.pop('payAtDoor',False),
              expirationDate=expiry,
          )
  
          # Anything passed by this form that is not an Event field (any extra fields) are
          # passed directly into the TemporaryRegistration's data.
          reg.data = non_event_listing or {}
  
          if regSession.get('marketing_id'):
              reg.data.update({'marketing_id': regSession.pop('marketing_id',None)})
  
          eventRegs = []
          grossPrice = 0
  
          for key,value in event_listing.items():
              this_event = associated_events.get(id=key)
  
              # Check if registration is still feasible based on both completed registrations
              # and registrations that are not yet complete
              this_role_id = value.get('role',None) if 'role' in permitted_keys else None
              soldOut = this_event.soldOutForRole(role=this_role_id,includeTemporaryRegs=True)
  
              if soldOut:
                  if self.request.user.has_perm('core.override_register_soldout'):
                      # This message will be displayed on the Step 2 page by default.
                      messages.warning(self.request,_(
                          'Registration for \'%s\' is sold out. Based on your user permission level, ' % this_event.name +
                          'you may proceed with registration.  However, if you do not wish to exceed ' +
                          'the listed capacity of the event, please do not proceed.'
                      ))
                  else:
                      # For users without permissions, don't allow registration for sold out things
                      # at all.
                      form.add_error(None, ValidationError(_('Registration for "%s" is tentatively sold out while others complete their registration.  Please try again later.' % this_event.name),code='invalid'))
                      return super(ClassRegistrationView,self).form_invalid(form)
  
              dropInList = [int(k.split("_")[-1]) for k,v in value.items() if k.startswith('dropin_') and v is True]
  
              # If nothing is sold out, then proceed to create a TemporaryRegistration and
              # TemporaryEventRegistration objects for the items selected by this form.  The
              # expiration date is set to be identical to that of the session.
  
              logger.debug('Creating temporary event registration for: %s' % key)
              if len(dropInList) > 0:
                  tr = TemporaryEventRegistration(
                      event=this_event, dropIn=True, price=this_event.getBasePrice(dropIns=len(dropInList))
                  )
              else:
                  tr = TemporaryEventRegistration(
                      event=this_event, price=this_event.getBasePrice(payAtDoor=reg.payAtDoor), role_id=this_role_id
                  )
              # If it's possible to store additional data and such data exist, then store them.
              tr.data = {k: v for k,v in value.items() if k in permitted_keys and k != 'role'}
              eventRegs.append(tr)
              grossPrice += tr.price
  
          # If we got this far with no issues, then save
          reg.priceWithDiscount = grossPrice
          reg.save()
          for er in eventRegs:
              er.registration = reg
              er.save()
  
          regSession["temporaryRegistrationId"] = reg.id
          regSession["temporaryRegistrationExpiry"] = expiry.strftime('%Y-%m-%dT%H:%M:%S%z')
          self.request.session[REG_VALIDATION_STR] = regSession
  
          if self.returnJson:
              return JsonResponse({
                  'status': 'success', 'redirect': self.get_success_url()
              })
          return HttpResponseRedirect(self.get_success_url())