[英]Django REST framework use AJAX url to point api detail url
我正在使用Django開發數據庫程序。 該程序從用戶的表單/導入的文件中追加數據庫,允許按類別列出數據,並按類別進行內聯編輯。
我做了很多研究(因為我是django的新人),到目前為止,我已經成功地生成了表格,並通過結合了rest框架和datatables來定制了表格。
當我嘗試對表實施內聯編輯時,會發生問題。 我使用插件數據表編輯器。 我的視圖和序列化程序似乎可以正常運行,因為我可以在Api根目錄中進行POST
, PUT
和DELETE
。 但是然后我無法使ajax url指向方法api詳細信息視圖,我需要url中的pk
是可變的以匹配選擇:
我的serializer.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'
)
我的views.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)
我的urls.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:{“詳細信息”:“未找到。”}
當我用特定數字替換ajax網址中的pk
時,我得到
錯誤400
JSON抱怨所有字段都不是必需的!
在這一點上,我已經被卡住了一段時間,但找不到解決我問題的答案...。我們將不勝感激!
這可能會幫助某人。
在數據表中,當在客戶端上處理CRUD方法並使用Django Rest Framwork api時,我們需要將正確的方法指向正確的url,這意味着:
POST
和GET
列表(因為我們沒有處理單個現有實例),因此在我的情況下,該網址為url: 'api/edit_tanks/'
PUT
, DELETE
和GET
實例的“詳細網址”(需要傳遞pk
來識別實例),可以使用AJAX _id_
獲取網址中的pk
。 所以我的網址是: url: 'api/edit_tanks/_id_'
這應該解決錯誤:
{“詳細信息”:“未找到。”}
對於“必填字段”錯誤,請確保在所有required=False
的字段中,在序列化器中指定required=False
。 我親自在所有字段中指定它,然后讓模型處理需求。
關於視圖(API視圖):
ModelViewSet
已經包含所有CRUD方法,可以隨時重寫以添加新參數或擁有自己的特定邏輯。 我的看法變成:
class TankViewSet(viewsets.ModelViewSet):
queryset = Tank.objects.all().order_by('tag')
serializer_class = TankSerializer
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.