簡體   English   中英

Django REST框架使用AJAX網址指向API詳細信息網址

[英]Django REST framework use AJAX url to point api detail url

我正在使用Django開發數據庫程序。 該程序從用戶的表單/導入的文件中追加數據庫,允許按類別列出數據,並按類別進行內聯編輯。

我做了很多研究(因為我是django的新人),到目前為止,我已經成功地生成了表格,並通過結合了rest框架和datatables來定制了表格。

當我嘗試對表實施內聯編輯時,會發生問題。 我使用插件數據表編輯器。 我的視圖和序列化程序似乎可以正常運行,因為我可以在Api根目錄中進行POSTPUTDELETE 但是然后我無法使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,這意味着:

  • 使用“列表網址”進行POSTGET列表(因為我們沒有處理單個現有實例),因此在我的情況下,該網址為url: 'api/edit_tanks/'
  • 用戶使用PUTDELETEGET實例的“詳細網址”(需要傳遞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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM