显示 table 将模型实例显示为行并让用户 select 实例(行)删除

display a table showing model instances as rows and let users select instances (rows) to delete

在我的应用中,用户可以上传文件。这些文件由具有关联元数据属性(上传时间、文件名、用户创建的注释、最大值等)的模型表示。

用户将上传多个文件,我想向他们展示他们上传的 table 个文件,每行旁边都有一个复选框,可用于删除所选文件和关联的模型实例。

我不确定正确的方法是什么,我查看了以下选项,但似乎没有明显的解决方案:

  1. 模型表格,使用CheckboxSelectMultiple

  2. django_tables2 - 似乎是一个成熟的第 3 方应用程序

  3. 重用 django 管理代码(表单和视图)。

默认的 django 管理应用程序行为非常适合我的用例,但我不确定重现它的最佳方法是什么?

app/models.py

import uuid

from django.contrib.auth import get_user_model
from django.db import models

User = get_user_model()


class Document(models.Model):
    def rename_file(self, filename):
        ext = filename.split('.')[-1]
        new_name = uuid.uuid4().hex

        return f'documents/{new_name}.{ext}'

    owner = models.ForeignKey(
        User,
        on_delete=models.CASCADE,
        editable=True,
    )
    document = models.FileField(upload_to=rename_file)
    notes = models.CharField(max_length=258, blank=True)
    uploaded_at = models.DateTimeField(auto_now_add=True)
    nice_name = models.CharField(max_length=128, null=True, blank=False)
    start_date = models.DateField(null=True, blank=False)
    end_date = models.DateField(null=True, blank=False)

    def __str__(self):
        return str(self.document)

app/admin.py

from django.contrib import admin

from .models import Document


def uuid(obj):
    return obj.owner.uuid


uuid.short_description = 'user id'


@admin.register(Document)
class DocumentAdmin(admin.ModelAdmin):
    fields = ('document', 'notes')
    list_display = (
        'owner',
        uuid,
        'document',
        'nice_name',
        'notes',
        'uploaded_at',
        'start_date',
        'end_date'
    )

app/forms.py

from django import forms
from django.forms.widgets import CheckboxSelectMultiple

from .models import Document


class DeleteDocumentsForm(forms.ModelForm):

    document = forms.ModelMultipleChoiceField(queryset=None, widget=forms.CheckboxSelectMultiple)
    nice_name = forms.ModelMultipleChoiceField(queryset=None, widget=forms.CheckboxSelectMultiple)


    def __init__(self, *args, **kwargs):
        user = kwargs.pop('user', None)
        qs = Document.objects.filter(owner_id=user)
        #  super(DeleteDocumentsForm, self).__init__(*args, **kwargs)
        super().__init__(*args, **kwargs)
        self.fields['document'].queryset = qs
        self.fields['nice_name'].queryset = qs.values('nice_name')

    #  document.fields['nice_name'].widget.attrs['readonly'] = True

    class Meta:
        model = Document
        fields = ('document', 'nice_name')
        widgets = {
            'document': CheckboxSelectMultiple,
            'nice_name': CheckboxSelectMultiple,
        }

要实现你想做的事情,你需要创建一个封装了一个table的表单。当 for 循环遍历数据库中的每个项目时,提供一个复选框,该复选框的值将是上传文件的唯一 ID。通过提交表单,您还可以提交这些 ID。

这就是您的观点:

<form action="." method="post">
   {% csrf_token %}
   <table>
      {% for upload in uploads %}
         <tr>
            <td><input type="checkbox" name="selected" value="{{ upload.id }}"></td>
            <td><img src="{{ upload.url }}" alt="image"></td>
            <td>{{ upload.name }}</td>
          </tr>
       {% endfor %}
   </table>
   <button type="submit">Delete</button>
</form>

一旦用户选择了一个或多个复选框,并在按下删除键后,您将收到一个查询字典,其中包含您可以在视图中按需处理的所选项目的 ID:

<QueryDict: {'csrfmiddlewaretoken': [''], 'selected': ['2', '3']}>

至于表格,我真的没有看到它有任何用处。