fhir-py
fhir-py copied to clipboard
[FR] Support for FHIRPatch
The lib is missing support for proper PATCH operations as defined in the standard: http://hl7.org/implement/standards/fhir/http.html#patch
According to the docs update/save with a given list of fields should use this operation.
Tested with HAPI FHIR 5.2.0
This feature is already implemented. Could you provide an example of your code?
Hi @mkizesov
thanks for your help. Comes the code:
client: SyncFHIRClient = get_client(async=False)
# get or create FHIR object
try:
patient: SyncFHIRResource = client.reference('Patient', id=str(user.username)).to_resource()
modifiedfields = [] #do a PATCH
except exceptions.ResourceNotFound:
modifiedfields = None #do a post
patient = client.resource('Patient', id=str(user.username))
# set telecom fields
if any(x in update_fields for x in ["email", "mobile", "phone"]):
if modifiedfields is not None:
modifiedfields.append("telecom")
try:
# https://github.com/beda-software/fhir-py/issues/66
getattr(patient, "telecom")
except KeyError:
patient.telecom = []
def update_or_create(system, telelist, entry):
updated = False
# update if system already exists in FHIR object
for i, t in enumerate(telelist):
if t["system"] == system:
updated = True
telelist[i] = entry
break
if not updated:
telelist.append(entry)
if "email" in update_fields:
update_or_create("email", patient.telecom, entry={
"system": 'email',
"value": str(user.email),
"use": 'home'
})
if "mobile" in update_fields:
update_or_create("sms", patient.telecom, entry={
"system": 'sms',
"value": str(user.mobile),
"use": 'mobile'
})
if "phone" in update_fields:
update_or_create("phone", patient.telecom, entry={
"system": 'phone',
"value": str(user.phone),
"use": 'home'
})
if "first_name" in update_fields or "last_name" in update_fields:
if modifiedfields is not None:
modifiedfields.append("name")
try:
# https://github.com/beda-software/fhir-py/issues/66
getattr(patient, "name")
except KeyError:
patient.name = [{}]
patient.name[0]["use"] = 'official'
if "first_name" in update_fields:
patient.name[0]["given"] = str(user.first_name)
patient.name[0]["text"] = f'{user.first_name} {patient.name[0].get("family", "")}'
if "last_name" in update_fields:
patient.name[0]["family"] = str(user.last_name)
patient.name[0]["text"] = f'{patient.name[0].get("given", "")} {user.last_name}'
if "birthdate" in update_fields:
if modifiedfields is not None:
modifiedfields.append("birthDate")
patient.birthDate = user.birthdate.isoformat()
if "gender" in update_fields:
if modifiedfields is not None:
modifiedfields.append("gender")
patient.gender = user.gender
if "is_active" in update_fields:
if modifiedfields is not None:
modifiedfields.append("active")
patient.active = user.is_active
patient.save(fields=modifiedfields)
So basically the purpose of the code is to update only attributes that have been updated on our side. What we try achieve is to implement some kind of sync-adapter that keeps the FHIR Server in sync with the client. However, as many clients write to the server we want to limit the usage of PUT as much as possible ;)
Best Patrick
Hi! Maybe it will worth if we just allow passing not only field names in save, for example:
resource.save(fhirpatch=[{"op": "add", "path": "path expr here", "value": "value to add"}])
It will be more flexible. What do you think? Will it solve the issue?
yes, should work. Maybe it makes sense to compute as well. Basically
- Define FHIR related resource by id
- change fields via Dot-notation e.g. tmpPatient.name = "ABC"
- Save changed/added fields via patch tmpPatient.save(partial_update=True)
For me that's always the nice use case to use patch, when I know that I want to add/change some specific params but try to avoid loading the whole resource in advance and PUT everything back, just for a couple of small changes (and risk that I run into raise conditions because it changed in the meanwhile).
https://github.com/beda-software/fhir-py/issues/68#issuecomment-866916629 is
patch
operation available ?
As I understand, fhir patch is not implemented yet. Only standard http PATCH operation (fhir update) is available using either resource.update(fieldToUpdate="")
or resource.save(fields=['fieldsToUpdate'])
.