I am working on this, too. I found a solution. I am also new to django and this solution is not elegant, but maybe other community members can give suggestions. Here is my (generalized) code which allows for the changing of an attribute “name” for a logged in “CustomUser” model object.
Here is the html where the changeable text is.
<!-- detail.html -->
<h2 contenteditable='true' id='name'>{{ object.name }}</h2>
...
<script src="{% static 'js/detail.js' %}" ></script>
Here is the javascript methods that get the new name as the user changes it and send a post request with the changed name. Ideally, this would only happen when the user finishes typing something new and clicks away, but I only figured out how to do it every time the user types a letter. The other thing I wanted to do was send back the old name that was there before (to be certain that the correct field is being changed), but until I fix this previous issue, I don’t think I can do that.
// detail.js
let name = document.getElementById("name")
let csrftoken = getCookie('csrftoken');
name.addEventListener("input", function() {
let newName = name.textContent # is this unsafe? I think it might be
let data = { name: newName }
fetch('change_name/', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
"X-CSRFToken": csrftoken,
},
body: JSON.stringify(data),
credentials: 'same-origin',
})
.then(response => response.json())
.then(data => {
console.log('Success: ', data)
})
.catch((error) => {
console.error('My Error: ', error)
})
}, false);
// The following function are copying from
// https://docs.djangoproject.com/en/dev/ref/csrf/#ajax
function getCookie(name) {
var cookieValue = null;
if (document.cookie && document.cookie !== '') {
var cookies = document.cookie.split(';');
for (var i = 0; i < cookies.length; i++) {
var cookie = cookies[i].trim();
// Does this cookie string begin with the name we want?
if (cookie.substring(0, name.length + 1) === (name + '=')) {
cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
break;
}
}
}
return cookieValue;
}
Here is the url where the post request goes.
# urls.py
urlpatterns = [
path(_('<str:pk>/change_name/'), change_name, name='change_name'),
...
]
Here is the method that gets the new name and calls a method on the user to change the name.
# views.py
def change_name(request, pk):
user = get_user_model().objects.get(username=pk)
data = json.loads(request.body)
new_name = data['name']
success = user.change_name(new_name)
...
return HttpResponseRedirect(reverse('detail', kwargs={'pk': pk}))
In my code I did not actually change the name for a user, I did something more specific to the project. But, I think something like this would work.
# models.py
class CustomUser(...):
...
def change_name(self, new_name):
self.name = new_name
self.save()
return self.name == new_name