For anyone still looking for an answer to this without using a spatialite format, I've found something that works.
If you have a csv and use a join to join it to a spatial layer, one of the options of the join is to cache the layer. You can get to this option if you go to the properties of your layer, then to the joined data and click edit join. If you disable the cache option, you can reload the data layer after the csv has changed and then trigger a repaint of your map to get a refreshed map view.
You can do the reloading and repainting in the Python Console. First, you have to define a name for the map canvas, the csv and for the layer:
mc = iface.mapCanvas()
layer=mc.currentLayer()
csv_layer=mc.currentLayer()
Be sure to have the layers active when you are naming them in the console when using the currentLayer method (it has to be the 'current layer').
Then, if you set the cache option as off for your join, you can alter the csv and then use the following two commands in the Python console to redraw your map:
csv_layer.reload()
layer.triggerRepaint()
This worked for me, but I only had 100 rows of data. It could be that operations will be slow without caching when you have a bigger dataset.