问题
I am new to JS, HTML, Django and all that related stuff, and I was not able to solve my problem on my own by reading documentation or using Google.
I want to save inline-changes using x-editable to the database in an django environment. The template below works perfectly, but now I would like to overwrite the database entries with the new names.
I tried to reduce the code to the relevant parts of my problem.
models.py:
class MyClass(models.Model):
name = models.CharField(max_length=120)
views.py:
def list(request):
return render(request, 'list.html', {'list':MyClass.objects.all()}
urls.py:
url(r'^list/$', 'myapp.views.list', name='list'),
list.html:
{% extends "base.html" %}
{% block content %}
<script>
$(document).ready(function() {
$.fn.editable.defaults.mode = 'inline';
$('.name').editable({
});
});
</script>
<h1>Names</h1>
<div>
<table border='1'>
{% for l in list %}
<tr><td><a class="name">{{ l.name }}</a></td></tr>
{% endfor %}
</table>
</div>
{% endblock %}
--------------------------------------------------------
My most promising approach was to create an update view.
def list_update(request, pk):
l = get_object_or_404(MyClass, pk=pk)
form = ListForm(request.POST or None, instance=l)
if form.is_valid():
form.save()
return redirect('list')
return render(request, '', {'form':form})
and add the following lines to the code above:
urls.py
url(r'^update/(?P<pk>\d+)$', 'myapp.views.list_update', name='list_update'),
list.html
$('.name').editable({
pk: l.pk,
url: '{% url 'list_update' l.pk%}',
});
But this attempt results in an NoReverseMatch error and l.pk seems to be empty. I appreciate any help on how to do this in the right way.
回答1:
urls.py:
url(r'^xed_post$', views.xed_post, name='xed_post'),
Django view code (function based) in views.py:
from django.http import JsonResponse
def xed_post(request):
"""
X-Editable: handle post request to change the value of an attribute of an object
request.POST['model']: name of Django model of which an object will be changed
request.POST['pk']: pk of object to be changed
request.POST['name']: name of the field to be set
request.POST['value']: new value to be set
"""
try:
if not 'name' in request.POST or not 'pk' in request.POST or not 'value' in request.POST:
_data = {'success': False, 'error_msg': 'Error, missing POST parameter'}
return JsonResponse(_data)
_model = apps.get_model('swingit', request.POST['model']) # Grab the Django model
_obj = _model.objects.filter(pk=request.POST['pk']).first() # Get the object to be changed
setattr(_obj, request.POST['name'], request.POST['value']) # Actually change the attribute to the new value
_obj.save() # And save to DB
_data = {'success': True}
return JsonResponse(_data)
# Catch issues like object does not exist (wrong pk) or other
except Exception as e:
_data = {'success': False,
'error_msg': f'Exception: {e}'}
return JsonResponse(_data)
then, in list.html:
{% extends "base.html" %}
{% block content %}
<script>
$(document).ready(function() {
$.fn.editable.defaults.mode = 'inline';
$('.name').editable({
params: {
csrfmiddlewaretoken:'{{csrf_token}}',
model:'MyClass'
},
url: '/xed_post',
error: function(response, newValue) {
return response.responseText;
},
success: function(response, newValue) {
if(!response.success) return response.error_msg;
}
});
});
</script>
<h1>Names</h1>
<div>
<table border='1'>
{% for l in list %}
<tr><td><a class="name" data-name="name" data-type="text" data-pk="{{ l.pk }}">{{ l.name }}</a></td></tr>
{% endfor %}
</table>
</div>
{% endblock %}
Note that using "name" for both the css class and the Django field name is confusing. data-name="name" refers to the Django field name, while class="name" refers to the css class.
回答2:
Davy's code doesn't work as is (for me).
But if you add:
$.ajaxSetup({
data: {csrfmiddlewaretoken: '{{ csrf_token }}' },
});
Before everything then it does, as long as you have {% csrf_token %}
somewhere in the html template. I simply put it at the top since I'm using X-editable's and there's no form tags in the template.
So add that {% csrf_token %}
line somewhere and change Davy's JS code to:
{% extends "base.html" %}
{% block content %}
<script>
$.ajaxSetup({
data: {csrfmiddlewaretoken: '{{ csrf_token }}' },
});
$(document).ready(function() {
$.fn.editable.defaults.mode = 'inline';
$('.name').editable({
params: {
model:'MyClass'
},
url: '/xed_post',
error: function(response, newValue) {
return response.responseText;
},
success: function(response, newValue) {
if(!response.success) return response.error_msg;
}
});
});
</script>
And it should work. Note that I removed the {{ csrf_token }}
line from the params
dictionary since the AJAX setup call takes care of it so it's not necessary (at least for my setup).
来源:https://stackoverflow.com/questions/31852816/save-changes-to-database-using-django-and-x-editable