有没有更好的方法来编写此代码以保持 DRY?

Is there a better way to write this code so DRY can be maintained?

我有2个模型

  1. 游览保存游览

  2. TourImage 保存与旅游相关的图片

    class Tour(models.Model):
        name = models.CharField(max_length=50)
    
    class TourImage(models.Model):
        tour = models.ForeignKey(Tour, on_delete=models.CASCADE)
        image = models.FileField(upload_to='images/')
    

在我的 views.py 文件中,我有以下代码来保存游览和游览图像

class CreateTourView(CreateView):
    model = Tour
    template_name = "create_tour.html"
    fields = "__all__"

    def form_valid(self, form):
        tour = form.save()
        for image in self.request.FILES.getlist("extra_images"):
            TourImage.objects.create(tour=tour, image=image)
    return super().form_valid(form)

HTML 表格如下所示

<form action="" method="post" enctype="multipart/form-data">
{% csrf_token %}
{{ form | crispy }}
<input type="file" name="extra_images" multiple />
<input type="submit" value="Save" />
</form>

这很好用,图像保存在数据库中。

但我还想添加选项来编辑Tour和添加额外的图像,所以UpdateView代码如下

class TourUpdateView(UpdateView):
    model = Tour
    template_name = "update_tour.html"
    fields = "__all__"

    def form_valid(self, form):
        tour = form.save()
        for image in self.request.FILES.getlist("extra_images"):
            TourImage.objects.create(tour=tour, image=image)
        return super().form_valid(form)

CreateView 和 UpdateView 的 .form_valid() 方法相同。

有没有更好的编码方式来避免重复代码?

你创建了一个mixin:

class TourImageMixin:
    model = Tour

    def <b>form_valid</b>(self, form):
        tour = form.save()
        for image in self.request.FILES.getlist('extra_images'):
            TourImage.objects.create(tour=tour, image=image)
        return super().form_valid(form)

然后你在两个视图中混合它:

class CreateTourView(<b>TourImageMixin,</b> CreateView):
    template_name = 'create_tour.html'
    fields = '__all__'

class TourUpdateView(<b>TourImageMixin,</b> UpdateView):
    template_name = "update_tour.html"
    fields = '__all__'

实际上使用了 Django 的视图,例如 ListView [classy CBV] are constructed with mixins that define certain behavior. For the ListView the MultipleObjectTemplateResponseMixin [Django-doc], TemplateResponseMixin [Django-doc] and MultipleObjectMixin [Django-doc]