首页 > 解决方案 > 基于 Django 类的 UpdateView 与多个上传文件的表单

问题描述

关于我目前面临的问题,我有两个问题:

  1. django 中的最佳实践是覆盖 CreateView 中的 post 方法吗?如果不是,您是否在 CategoryFullForm 或 CreateView 上编写表单 _valid 函数,它看起来如何?CreateView 目前工作得很好,但要确保没有更好的方法来做到这一点。

  2. 如果这是最佳实践,您将如何覆盖 UpdateView 中的 get 函数,以便能够编辑与正在上传的实例相关的文件,甚至添加额外的文件?也可以通过其他方式完成此任务。

模型.py

############ CATEGORY MODEL ################
class Category(models.Model):
    category_id = models.AutoField(primary_key=True)
    name = models.CharField(max_length=100, null=True, blank=True)
    est_pr_sqft = models.FloatField(blank=True)
    est_duration = models.IntegerField(blank=True)
    preceding_job = models.CharField(max_length=100, blank=True)
    category_notes = models.CharField(max_length=250, blank=True)
    category_slug = models.SlugField(max_length=100, unique=True, null=False)
    author = models.ForeignKey(User, on_delete=models.CASCADE, default=1)
    date_posted = models.DateTimeField(auto_now_add=True)
    date_modified = models.DateTimeField(auto_now=True)

    def __str__(self):
        return self.name

    def get_absolute_url(self):
        return reverse('category-detail', kwargs={'slug': self.category_slug})

    def save(self, *args, **kwargs):
        if not self.category_slug:
            self.category_slug = slugify(self.name)
        return super().save(*args, **kwargs)

class CategoryFiles(models.Model):
    category_id = models.ForeignKey(Category, on_delete=models.CASCADE)
    document = models.FileField(upload_to="attachments",null=True,blank=True)
    uploaded_date = models.DateTimeField(auto_now_add=True)
    modified_date = models.DateTimeField(auto_now=True)

    def delete(self, *args, **kwargs):
        self.document.delete()
        return super().delete(*args, **kwargs)

表格.py

class CategoryForm(forms.ModelForm):

    class Meta:
        model = Category
        fields = ['name', 'est_pr_sqft', 'est_duration', 'preceding_job', 'category_notes']

class CategoryFullForm(CategoryForm):

    files = forms.FileField(widget=forms.ClearableFileInput(attrs={'multiple': True}),required=False)

    class Meta(CategoryForm.Meta):
        fields = CategoryForm.Meta.fields + ['files']

视图.py

####### CATEGORY VIEWS ########

class CategoryListView(LoginRequiredMixin, ListView):
    model = Category
    template_name = 'ProjectManagementApp/PM-Category-List.html'
    context_object_name = 'categories'
    slug_field = 'project_slug'
    success_url = reverse_lazy('Category-list')

class CategoryDetailView(LoginRequiredMixin, DetailView):
    model = Category
    template_name = 'ProjectManagementApp/PM-Category-Detail.html'
    slug_field = 'category_slug'

    def get_context_data(self, **kwargs):
        context = super(CategoryDetailView, self).get_context_data(**kwargs)
        context['files'] = CategoryFiles.objects.all()
        #context['photos'] = CategoryPhotos.objects.all()
        return context

class CategoryCreateView(LoginRequiredMixin, CreateView):
    model = Category
    form_class = CategoryFullForm
    template_name = 'ProjectManagementApp/PM-Category-Create.html'  # Replace with your template.
    #success_url = reverse_lazy('category-detail')
    slug_field = 'category_slug'

    def post(self, request, *args, **kwargs):
        form_class = self.get_form_class()
        form = self.get_form(form_class)
        files = request.FILES.getlist('files')
        if form.is_valid():
            author = request.user
            name = form.cleaned_data['name']
            est_pr_sqft = form.cleaned_data['est_pr_sqft']
            est_duration = form.cleaned_data['est_duration']
            preceding_job = form.cleaned_data['preceding_job']
            category_notes = form.cleaned_data['category_notes']
            category_obj = Category.objects.create(name=name,est_pr_sqft=est_pr_sqft,est_duration=est_duration,preceding_job=preceding_job,category_notes=category_notes,author=author)
            for f in files:
                CategoryFiles.objects.create(category_id=category_obj,document=f)

            return HttpResponseRedirect(reverse_lazy('Category-list'))
        else:
            return self.form_invalid(form)

class CategoryUpdateView(LoginRequiredMixin, UpdateView): #UserPassesTestMixin - makes sure user who made entry is only one who can update it.
    model = Category
    form_class = CategoryFullForm
    template_name = 'ProjectManagementApp/PM-Category-Create.html'  # Replace with your template.
    slug_field = 'category_slug'
    success_url = reverse_lazy('Category-list')

    def post(self, request, *args, **kwargs):
        form_class = self.get_form_class()
        form = self.get_form(form_class)
        files = request.FILES.getlist('files')
        if form.is_valid():
            author = request.user
            name = form.cleaned_data['name']
            est_pr_sqft = form.cleaned_data['est_pr_sqft']
            est_duration = form.cleaned_data['est_duration']
            preceding_job = form.cleaned_data['preceding_job']
            category_notes = form.cleaned_data['category_notes']
            category_obj = Category.objects.create(name=name,est_pr_sqft=est_pr_sqft,est_duration=est_duration,preceding_job=preceding_job,category_notes=category_notes,author=author)
            for f in files:
                CategoryFiles.objects.create(category_id=category_obj,document=f)

            return HttpResponseRedirect(reverse_lazy('Category-list'))
        else:
            return self.form_invalid(form)
#
#    #Doesnt allow you to update other users post
#    #def test_func(self):
#    #    project = self.get_object()
#    #    if self.request.user == post.author:
#    #        return True
#    #    return False
#
#
    def form_valid(self,form):
        form.instance.author = self.request.user
        return super().form_valid(form)

class CategoryDeleteView(LoginRequiredMixin, DeleteView): #UserPassesTestMixin - makes sure user who made entry is only one who can update it.
    model = Category
    template_name = 'ProjectManagementApp/PM-Category-Delete.html'
    slug_field = 'category_slug'
    success_url = reverse_lazy('Category-list')


    #Doesnt allow you to delete other users post
    #def test_func(self):
    #    project = self.get_object()
    #    if self.request.user == post.author:
    #        return True
    #    return False

如果需要 urls.py/admin.py,我很乐意提供,但不要认为它们是必需的,以及任何 html 文件。

标签: pythondjangodjango-formsdjango-class-based-viewsmultifile-uploader

解决方案


推荐阅读