In order to avoid this kind of loop, you need to disconnect at the beginning of your custom method, and then reconnect to signal afterwards :
Inside your method connected to signal :
signals.post_save.disconnect(YourModel.your_custom_method, sender=YourModel)
# Do your stuff
instance.save()
signals.post_save.connect(YourModel.your_custom_method, sender=YourModel)
Note : I'm using "YourModel.your_custom_method because I tend to place it inside the model, this is obviously not mandatory.
EDIT :
This SO question brings the use of update() instead of save() as a cleaner way, it might be what you're looking for.
Django post_save preventing recursion without overriding model save()
Although it might be cleaner I wouldn't think of it as a perfect solution unless properly managed with caching, since you'll be forced to hit the database to retrieve the queryset while you already have the instance in your hands as argument of the signal...
The idea of save_without_signal seems interesting but I wonder how it could be done without the above caveats.
Hope this helps,
Regards,