Django REST框架使用AJAX url来指向api细节url



我正在使用Django开发数据库程序。该程序从用户的表单/导入的文件中附加数据库,允许按类别列出数据,并按类别进行内联编辑。

我做了很多研究(因为我是django的新手(,到目前为止,我已经成功地生成了表单,并通过组合rest框架和数据表来定制表。

当我尝试对表实现内联编辑时,就会出现这个问题。我使用插件数据表编辑器。我的视图和序列化程序似乎可以工作,因为我可以在Api根中使用POSTPUTDELETE。但是我不能让ajax url指向方法api的详细视图,我需要url中的pk是可变的,以匹配选择:

我的序列化程序.py

class TankSerializer(serializers.ModelSerializer):
modified_date = serializers.DateTimeField(format='%d/%m/%Y %H:%M', input_formats=None)
updated_by = serializers.SlugRelatedField(slug_field='last_name', queryset=User.objects.all())
pid = serializers.SlugRelatedField(slug_field='number', queryset=PID.objects.all())
zone = serializers.SlugRelatedField(slug_field='number', queryset=ProcessZone.objects.all())
medium = serializers.SlugRelatedField(slug_field='code', queryset=Medium.objects.all())
revision = serializers.SlugRelatedField(slug_field='code', queryset=Revision.objects.all())
supplier = serializers.SlugRelatedField(slug_field='name', queryset=Supplier.objects.all())
po = serializers.SlugRelatedField(slug_field='number', queryset=PO.objects.all())
material = serializers.SlugRelatedField(slug_field='name', queryset=Material.objects.all())
DT_RowId = serializers.SerializerMethodField()
def get_DT_RowId(self, tank):
return 'row_%d' % tank.pk
class Meta:
model = Tank
fields = (
'DT_RowId', 'tag', 'description', 'pid', 'zone', 
'medium', 'revision', 'supplier', 'po', 'material', 
'volume', 'hight','modified_date','updated_by', 'created_by'
)

我的观点.py

@login_required
@ensure_csrf_cookie
def edit_tanks(request, project_code):
project = get_object_or_404(Project, code=project_code)
return render(request, 'edit_tanks.html', {'project': project})
class TankViewSet(viewsets.ModelViewSet):
queryset = Tank.objects.all().order_by('tag')
serializer_class = TankSerializer
lookup_filed = 'pk'
@action(methods=['get'], detail=True)   
def get(self, request, pk, project_code, format=None):
serializer = self.serializer_class(self.queryset, many=True)
return Response(serializer.data)
@action(methods=['post'], detail=True)
def post(self, request, pk=None, format=None):
serializer = self.serializer_class(data=request.data)
if serializer.is_valid():
serializer.save()
return Response(serializer.data, status.HTTP_201_CREATED)
return Response(serializer.errors, status.HTTP_400_BAD_REQUEST)
@action(methods=['patch'], detail=True)
def patch(self, request, pk, format=None):
queryset = self.get_object(pk)
serializer = self.serializer_class(queryset, data=request.data, partial=True)
if serializer.is_valid():
serializer.save()
return Response(serializer.data)
return Response(serializer.errors, status.HTTP_400_BAD_REQUEST)
@action(methods=['put'], detail=True)
def put(self, request, pk, format=None):
queryset = self.get_object(pk)
serializer = self.serializer_class(queryset, data=request.data)
if serializer.is_valid():
serializer.save()
return Response(serializer.data)
return Response(serializer.errors, status.HTTP_400_BAD_REQUEST)
@action(methods=['delete'], detail=True)
def delete(self, request, pk, format=None):
queryset = self.get_object(pk)
queryset.delete()
return Response(status.HTTP_204_NO_CONTENT)

我的网址.py

router = routers.DefaultRouter()
router.register(r'edit_tanks', views.TankViewSet, 'edit_tanks')
urlpatterns = [
re_path(r'^projects/(?P<project_code>d+)/engineering/equipment/edit_tanks/api/', include(router.urls)),
re_path(r'^projects/(?P<project_code>d+)/engineering/equipment/edit_tanks/$', views.edit_tanks, name='edit_tanks'),
path('admin/', admin.site.urls),
]

我的模板edit_tanks.html

{% block content %}
<div class="row">
<div class="col-sm-12">
<table id="edit_tanks" class="stripe row-border order-column" cellspacing="0" style="table-layout: auto; width:100%;">
<thead>
<tr>
<th></th>
<th>Tag</th>
<th>Description</th>
<th>PID</th>
<th>Zone</th>
<th>Medium</th>
<th>Revision</th>
<th>Supplier</th>
<th>PO</th>
<th>Material</th>
<th>Volume</th>
<th>Height</th>
<th>Last updated</th>
<th>Updated by</th>
</tr>
</thead>
</table>
</div>
</div>
{% endblock %}
{% block extra_js %}
<script type="text/javascript">

var editor;
$(document).ready(function() {
editor = new $.fn.dataTable.Editor( {
ajax: {
create: {
type: 'POST',
url: 'api/edit_tanks/?format=datatables',
},
edit: {
type: 'PUT',
url: 'api/edit_tanks/{{tank_pk}}/',
},
remove: {
type: 'DELETE',
url: 'api/edit_tanks/{{tank_pk}}/',
}
},
table: "#edit_tanks",
fields: [ {
label: "Tag:",
name: "tag"
}, {
label: "Description:",
name: "description"
}, {
label: "Ravision:",
name: "revision.code",
type: "select"
}, {
label: "PO:",
name: "po.number",
type: "select"
},
]
} );    
// Activate an inline edit on click of a table cell
$('#edit_tanks').on( 'click', 'tbody td:not(:first-child)', function (e) {
editor.inline( this );
} );
var table = $('#edit_tanks').DataTable({
"processing": true,
"serverSide": true,
ajax: {
url: "api/edit_tanks/?format=datatables",
data: { 
csrfmiddlewaretoken: "{{ csrf_token }}"
}
},
dom: 'Bfrtip',
language: {
search: "_INPUT_",
searchPlaceholder: "Search..."
},
"columns": [
{
data: null,
defaultContent: '',
className: 'select-checkbox',
orderable: false
},
{"data": "tag"},
{"data": "description"},
{"data": "pid", "number": "pid.number"},
{"data": "zone", "number": "zone.number"},
{"data": "medium", "code": "medium.code"},
{"data": "revision", "code": "revision.code"},
{"data": "supplier", "name": "supplier.name"},
{"data": "po", "number": "po.number"},
{"data": "material", "name": "material.name"},
{"data": "volume"},
{"data": "hight"},
{"data": "modified_date"},
{"data": "updated_by", "last_name": "user.last_name"},
],
autoFill: {
columns: ':not(:first-child)',
editor:  editor
},
keys: {
columns: ':not(:first-child)',
editor:  editor
},
select: {
style:    'os',
selector: 'td:first-child',
blurable: true
},
buttons: [ 
{ extend: "create", editor: editor},
{ extend: "edit",   editor: editor },
{
extend: "selected",
text: 'Duplicate',
action: function ( e, dt, node, config ) {
// Start in edit mode, and then change to create
editor
.edit( table.rows( {selected: true} ).indexes(), {
title: 'Duplicate record',
buttons: 'Create from existing'
} )
.mode( 'create' );
}
},
{ extend: "remove", editor: editor }
]
});
});
</script>
{% endblock %}

当我尝试编辑或内联编辑时,我会得到

错误404 JSON:{"detail":"未找到。"}

当我用特定的数字替换ajax url中的pk时,我得到

错误400

和JSON抱怨所有字段都是必需的,而不是必需的!

我已经被困在这一点上一段时间了,我找不到解决我问题的答案。。。。任何帮助都将不胜感激!

这可能会对某人有所帮助。。。。

在Datatables中,当在客户端处理CRUD方法并使用Django Rest Framwork api时,我们需要将正确的方法指向正确的url,这意味着:

  • POSTGET使用"list url"作为列表(因为我们没有处理单个现有实例(,所以在我的情况下,url将是url: 'api/edit_tanks/'
  • 用户为PUTDELETEGET创建一个实例的"详细url"(需要传递pk来标识该实例(,在AJAX中_id_可以用来获取url中的pk。所以我的网址是:url: 'api/edit_tanks/_id_'

这应该可以解决错误:

{"detail":"未找到。"}

对于"字段是必需的"错误,请确保在序列化程序中在所有不必需的字段中指定required=False。我个人在所有领域都指定了它,并让模型处理需求。

关于视图(API视图(:

ModelViewSet已经包含了所有的CRUD方法,可以随时重写以添加新的参数或自己的特定逻辑。我的观点变成:

class TankViewSet(viewsets.ModelViewSet):
queryset = Tank.objects.all().order_by('tag')
serializer_class = TankSerializer 

最新更新