Django Class based UpdateView with Form for Multiple Uploaded Files
Asked Answered
K

0

2

I have two questions in regards to the problem I am currently facing:

  1. Is it best practice in django to overwrite the post method in the CreateView? If it isn't do you write a form _valid function on the CategoryFullForm or in the CreateView and how would it look? The CreateView currently works great, but want to make sure there isn't a better way to do this.

  2. If this is best practice, how would you override the get function in the UpdateView so you would be able to edit the files that relate to the instance being uploaded and even add an additional File? Open to other ways to accomplish this task as well.

models.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)

forms.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']

views.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

If the urls.py/admin.py are needed am happy to provide, but don't think they are needed, as well as any of the html files.

Konikow answered 20/5, 2020 at 0:21 Comment(1)
I think you would have more success at an answer if you simplified your question to generic forms of your models. They are currently too verbose.Hanes

© 2022 - 2024 — McMap. All rights reserved.