【问题标题】:Multiple Images Upload Field in DjangoDjango中的多个图像上传字段
【发布时间】:2020-02-18 10:55:59
【问题描述】:

我是 Django 新手,我正在使用 this tutorial 在我的 Web 应用程序的模型中添加多图像上传字段。到目前为止,我在如何将我的 Photo Model 关联到 HotelCreateView 上的酒店模型。我的问题是如何将这个多张图片与我的酒店模型相关联,以便在创建酒店时上传的图片链接到创建的酒店。请协助。

非常感谢

酒店模型

class Hotels(models.Model):
    """Stores all the information about the hotel and also used to query hotels"""

    name = models.CharField(max_length=255) #The name of the hotel
    address = models.CharField(max_length=255)
    city = models.CharField(max_length=255)
    country = models.CharField(max_length=255)
    mobile_number = models.CharField(max_length=12)
    created_at = models.DateTimeField(default=timezone.now)
    last_modified = models.DateTimeField(auto_now=True)
    description = models.TextField()
    slug = models.SlugField(unique=True)
    property_photo = models.ImageField(default='default.jpg', upload_to='hotel_photos')
    star_rating = models.PositiveIntegerField()
    contact_person = models.ForeignKey(UserProfile, on_delete=models.SET_NULL, null=True, blank=True,) #Owner of the hotel or person who created the hotel

    class Meta:
        unique_together = ('name', 'slug')
        verbose_name_plural = 'Hotels'  

照片模特

class Photo(models.Model):
    title = models.CharField(max_length=255, blank=True)
    file = models.ImageField(upload_to='hotel_photos')
    hotel = models.ForeignKey(Hotels,on_delete=models.SET_NULL, null=True, blank=True,)

    class Meta:
        verbose_name_plural = 'Photos'


    def __str__(self):
        """Prints the name of the Photo"""
        return f'{self.hotel} photos'

Forms.py

class PhotoForm(forms.ModelForm):
    class Meta:
        model = Photo
        fields = ('hotel','file', )

Views.py

class PhotoUploadView(LoginRequiredMixin,View):
    def get(self, request):
        photos_list = Photo.objects.all()
        return render(self.request, 'hotels/uploads.html', {'photos': photos_list})

    def post(self, request):
        form = PhotoForm(self.request.POST, self.request.FILES, self.request.user)
        if form.is_valid():
            photo = form.save(commit=False)
            photo.hotel = self.request.hotel.contact_person
            photo.save()
            data = {'is_valid': True, 'name': photo.file.name, 'url': photo.file.url}
        else:
            data = {'is_valid': False}
        return JsonResponse(data)

【问题讨论】:

  • “我被卡住了”并没有解释确切的问题是什么。你看到错误了吗?是不是发生了不该发生的事情?解释您的代码当前正在做什么,也许我们可以提供帮助。
  • 代码可以上传照片,但照片与我希望的酒店模型没有关联
  • 如果照片上传页面是针对特定酒店的,那么如果该页面的 URL 包含酒店的 id,例如/hotels/<id>/photos/upload 这样,您将酒店的 id 传递给视图,并可以使用该 id 获取酒店(然后您应该检查酒店是否属于当前用户,以确保)。

标签: python django


【解决方案1】:

您说允许上传照片的小部件位于酒店创建页面上。这是一个问题,因为这意味着上传照片时尚未创建酒店。所以上传的照片不会有可以关联的hotel

有两种选择:

  • 将上传照片的步骤移至第二个步骤,酒店创建之后。将刚刚创建的酒店 ID 添加到您为 PhotoUploadView 调用的 url 中,以便将其作为 kwarg 传递给视图。
    # in PhotoUploadView, post()
    if form.is_valid():
        photo = form.save(commit=False)
        try:
            hotel = Hotel.objects.get(
                contact_person=self.request.user.userprofile,  # make sure hotel belongs to user
                id=self.kwargs.get('hotel_id'))
        except Hotel.DoesNotExist:
            raise Http404
        photo.hotel = hotel
        photo.save()
    
  • 在用户会话中跟踪上传的图片,并在提交HotelCreationForm 后将上传的图片关联到酒店:

    # in PhotoUploadView, post()
    if form.is_valid():
        photo = form.save()
        session = self.request.session
        if not session.get('uploaded_photos'):
            session['uploaded_photos'] = [] 
        session['uploaded_photos'].append(photo.id)
        data = {'is_valid': True, 'name': photo.file.name, 'url': photo.file.url}
    
    # in HotelCreationView, form_valid() or post():
    hotel = form.save()
    session = self.request.session
    if 'uploaded_photos' in session:
        Photo.objects.filter(id__in=session['uploaded_photos']).update(hotel=hotel)
        del session['uploaded_photos']
    

    请注意,在这种情况下,您需要在您的 Photo 模型中的 hotel 字段中保留 null=True, blank=True,因为您第一次保存没有酒店的照片。

    另请注意,如果用户从未完成保存酒店,照片仍将保存在数据库和存储中,与酒店无关,因此您可能需要不时清理(删除所有未保存的照片没有酒店)。

【讨论】:

  • 非常感谢先生。我选择了你的第一个选项。但是我做了一个小的编辑并将酒店查询更改为hotel = Hotels.objects.get(contact_person = self.request.user, id=Hotels.objects.last().id),因为您的查询给了我 404 not found 错误。现在我可以附加多个图像并链接到酒店。非常感谢!
  • 但是使用last() 是个坏主意。如果多个用户同时创建酒店,您无法保证这是正确的酒店。
  • 哎呀..我不知道我在想什么..我得再看看它
  • 正如我所说,您必须以某种方式传递hotelid。在您视图的 url 中或作为表单中的隐藏字段。
  • 我发现我做错了什么。我没有在 URL 中传递创建的酒店 ID,这就是我收到 404 错误的原因。我已经能够修复它,您的代码终于可以正常工作了。谢谢
【解决方案2】:

模型没有什么问题,但您需要对Photo 模型进行一些更改

class Photo(models.Model):
    title = models.CharField(max_length=255, blank=True)
    file = models.ImageField(upload_to='hotel_photos')
    hotel = models.ForeignKey(Hotels,on_delete=models.SET_NULL, related_name='photos')

现在您应该首先创建酒店对象,然后当您点击视图以添加图像时,它应该通过将酒店 ID 传递给它或类似的方式将酒店设置到其中。在其他情况下,您将使用 hotel 对象时,您可以通过使用 related_name 来直接访问其照片。

如果您无法事先创建酒店或类似的东西,也存在解决此问题的其他方法,但对于当前情况,这种方法可以工作。

【讨论】:

  • 抱歉,这似乎是一个愚蠢的问题。我如何传递酒店ID?如何获取已创建酒店的当前酒店 ID?
  • 您的完整用例是什么?您是否先创建酒店?如果是,并且您正在使用任何前端框架,因此只需在创建酒店时返回 id,然后在点击照片的发布视图时只需传递该 id 以创建链接但是您需要提及您的确切流程,以便我们可以想到最佳解决方案为它
  • 不需要设置related_name,没有它你可以使用hotel.photo_set.all()访问hotel实例的照片。另请注意,OP 特别提到他正在使用 ajax 从酒店创建页面上传照片,因此尚未创建酒店。
猜你喜欢
  • 2013-10-03
  • 1970-01-01
  • 2015-04-21
  • 2020-08-06
  • 2018-12-11
  • 2010-10-29
  • 2015-06-14
  • 2010-10-10
  • 2021-12-07
相关资源
最近更新 更多