def create(self, request): """ Does not work in Swagger! Create a new Property from a building file. --- consumes: - multipart/form-data parameters: - name: organization_id type: integer required: true - name: cycle_id type: integer required: true - name: file_type type: string enum: ["Unknown", "BuildingSync", "HPXML"] required: true - name: file description: In-memory file object required: true type: file """ if len(request.FILES) == 0: return JsonResponse({ 'success': False, 'message': 'Must pass file in as a Multipart/Form post' }) the_file = request.data['file'] file_type = BuildingFile.str_to_file_type( request.data.get('file_type', 'Unknown')) organization_id = request.data['organization_id'] cycle = request.data.get('cycle_id', None) if not cycle: return JsonResponse({ 'success': False, 'message': 'Cycle ID is not defined' }) else: cycle = Cycle.objects.get(pk=cycle) # figure out if file is xml or zip the_filename = the_file._get_name() tmp_filename, file_extension = os.path.splitext(the_filename) # initialize p_status = True property_state = True messages = {'errors': [], 'warnings': []} if file_extension == '.zip': # ZIP FILE, extract and process files one by one # print("This file is a ZIP") with zipfile.ZipFile(the_file, "r", zipfile.ZIP_STORED) as openzip: filelist = openzip.infolist() for f in filelist: # print("FILE: {}".format(f.filename)) # process xml files if '.xml' in f.filename and '__MACOSX' not in f.filename: # print("PROCESSING file: {}".format(f.filename)) data_file = NamedTemporaryFile() data_file.write(openzip.read(f)) data_file.seek(0) size = os.path.getsize(data_file.name) content_type = 'text/xml' # print("DATAFILE:") # print(data_file) a_file = InMemoryUploadedFile(data_file, 'data_file', f.filename, content_type, size, charset=None) building_file = BuildingFile.objects.create( file=a_file, filename=f.filename, file_type=file_type, ) p_status_tmp, property_state_tmp, property_view, messages_tmp = building_file.process( organization_id, cycle) # print('messages_tmp: ') # print(messages_tmp) # append errors to overall messages for i in messages_tmp['errors']: messages['errors'].append(f.filename + ": " + i) for i in messages_tmp['warnings']: messages['warnings'].append(f.filename + ": " + i) if not p_status_tmp: # capture error p_status = p_status_tmp else: # capture a real property_state (not None) property_state = property_state_tmp else: # just an XML building_file = BuildingFile.objects.create( file=the_file, filename=the_file.name, file_type=file_type, ) p_status, property_state, property_view, messages = building_file.process( organization_id, cycle) if p_status and property_state: if len(messages['warnings']) > 0: return JsonResponse({ 'success': True, 'status': 'success', 'message': { 'warnings': messages['warnings'] }, 'data': { 'property_view': PropertyViewAsStateSerializer(property_view).data, # 'property_state': PropertyStateWritableSerializer(property_state).data, }, }) else: return JsonResponse({ 'success': True, 'status': 'success', 'message': { 'warnings': [] }, 'data': { 'property_view': PropertyViewAsStateSerializer(property_view).data, # 'property_state': PropertyStateWritableSerializer(property_state).data, }, }) else: return JsonResponse( { 'success': False, 'status': 'error', 'message': messages }, status=status.HTTP_400_BAD_REQUEST)
def update_with_building_sync(self, request, pk): """ Does not work in Swagger! Update an existing PropertyView with a building file. Currently only supports BuildingSync. --- consumes: - multipart/form-data parameters: - name: pk description: The PropertyView to update with this buildingsync file type: path required: true - name: organization_id type: integer required: true - name: cycle_id type: integer required: true - name: file_type type: string enum: ["Unknown", "BuildingSync"] required: true - name: file description: In-memory file object required: true type: file """ if len(request.FILES) == 0: return JsonResponse({ 'success': False, 'message': "Must pass file in as a Multipart/Form post" }) the_file = request.data['file'] file_type = BuildingFile.str_to_file_type( request.data.get('file_type', 'Unknown')) organization_id = request.query_params.get('organization_id', None) cycle_pk = request.query_params.get('cycle_id', None) if not cycle_pk: return JsonResponse({ 'success': False, 'message': "Cycle ID is not defined" }) else: cycle = Cycle.objects.get(pk=cycle_pk) result = self._get_property_view(pk, cycle_pk) p_status = False new_pv_state = None if result.get('status', None) != 'error': building_file = BuildingFile.objects.create( file=the_file, filename=the_file.name, file_type=file_type, ) property_view = result.pop('property_view') previous_state = property_view.state # passing in the existing propertyview allows it to process the buildingsync file and attach it to the # existing propertyview. p_status, new_pv_state, new_pv_view, messages = building_file.process( organization_id, cycle, property_view=property_view) # merge the relationships from the old property state self._merge_relationships(previous_state, new_pv_state) else: messages = [ 'Cannot match a PropertyView with property_id=%s; cycle_id=%s' % (pk, cycle_pk) ] if p_status and new_pv_state: return JsonResponse({ 'success': True, 'status': 'success', 'message': 'successfully imported file', 'data': { 'property_view': PropertyViewAsStateSerializer(new_pv_view).data, }, }) else: return JsonResponse( { 'status': 'error', 'message': "Could not process building file with messages {}".format( messages) }, status=status.HTTP_400_BAD_REQUEST)
def create(self, request): """ Does not work in Swagger! Create a new Property from a building file. --- consumes: - multipart/form-data parameters: - name: organization_id type: integer required: true - name: cycle_id type: integer required: true - name: file_type type: string enum: ["Unknown", "BuildingSync", "GeoJSON", "HPXML"] required: true - name: file description: In-memory file object required: true type: file """ if len(request.FILES) == 0: return JsonResponse({ 'success': False, 'message': "Must pass file in as a Multipart/Form post" }) the_file = request.data['file'] file_type = BuildingFile.str_to_file_type(request.data.get('file_type', 'Unknown')) organization_id = request.data['organization_id'] cycle = request.data.get('cycle_id', None) if not cycle: return JsonResponse({ 'success': False, 'message': "Cycle ID is not defined" }) else: cycle = Cycle.objects.get(pk=cycle) building_file = BuildingFile.objects.create( file=the_file, filename=the_file.name, file_type=file_type, ) p_status, property_state, property_view, messages = building_file.process(organization_id, cycle) if p_status and property_state: return JsonResponse({ "status": "success", "message": "successfully imported file", "data": { "property_view": PropertyViewAsStateSerializer(property_view).data, # "property_state": PropertyStateWritableSerializer(property_state).data, }, }) else: return JsonResponse({ "status": "error", "message": "Could not process building file with messages {}".format(messages) }, status=status.HTTP_400_BAD_REQUEST)