将通用图像字段添加到django中的ModelForm中 [英] Adding a generic image field onto a ModelForm in django

查看:515
本文介绍了将通用图像字段添加到django中的ModelForm中的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有两个模型,房间图像图像是一种可以粘贴到任何其他模型的通用模型。我想给用户一个表单上传一个图像,当他们发布关于房间的信息。我已经编写了代码,但是我很难做到这一点,特别是在一种违反DRY的方式。

I have two models, Room and Image. Image is a generic model that can tack onto any other model. I want to give users a form to upload an image when they post information about a room. I've written code that works, but I'm afraid I've done it the hard way, and specifically in a way that violates DRY.

希望有人能一点更熟悉django形式可以指出我错了什么。

Was hoping someone who's a little more familiar with django forms could point out where I've gone wrong.

更新:

我试图澄清为什么选择这个设计在评论当前的答案。总而言之:

I've tried to clarify why I chose this design in comments to the current answers. To summarize:

我并没有在房间 c ImageField code> model,因为我想要多个与房间模型相关联的图像。我选择了一个通用的图像模型,因为我想将图像添加到几个不同的模型。我认为的替代方案是单个 Image 类上的多个外键,看起来很乱,或者多个 Image 我以为会混乱我的模式。我没有在我的第一篇文章中做出这一点,所以很抱歉。

I didn't simply put an ImageField on the Room model because I wanted more than one image associated with the Room model. I chose a generic Image model because I wanted to add images to several different models. The alternatives I considered were were multiple foreign keys on a single Image class, which seemed messy, or multiple Image classes, which I thought would clutter my schema. I didn't make this clear in my first post, so sorry about that.

目前看来,没有一个答案解决了如何使这更多干我确实想出了自己的解决方案,即将上传路径添加为图像模型中的类属性,并在每次需要时引用。

Seeing as none of the answers so far has addressed how to make this a little more DRY I did come up with my own solution which was to add the upload path as a class attribute on the image model and reference that every time it's needed.

# Models
class Image(models.Model):
    content_type = models.ForeignKey(ContentType)
    object_id = models.PositiveIntegerField()
    content_object = generic.GenericForeignKey('content_type', 'object_id')
    image = models.ImageField(_('Image'),
                                height_field='',
                                width_field='',
                                upload_to='uploads/images',
                                max_length=200)
class Room(models.Model):
    name = models.CharField(max_length=50)
    image_set = generic.GenericRelation('Image') 

# The form
class AddRoomForm(forms.ModelForm):
    image_1 = forms.ImageField()

    class Meta:
        model = Room

# The view
def handle_uploaded_file(f):

    # DRY violation, I've already specified the upload path in the image model
    upload_suffix = join('uploads/images', f.name)
    upload_path = join(settings.MEDIA_ROOT, upload_suffix)
    destination = open(upload_path, 'wb+')
    for chunk in f.chunks():
        destination.write(chunk)
    destination.close()
    return upload_suffix

def add_room(request, apartment_id, form_class=AddRoomForm, template='apartments/add_room.html'):
    apartment  = Apartment.objects.get(id=apartment_id)

    if request.method == 'POST':
        form = form_class(request.POST, request.FILES)
        if form.is_valid():
            room = form.save()
            image_1 = form.cleaned_data['image_1']

            # Instead of writing a special function to handle the image, 
            # shouldn't I just be able to pass it straight into Image.objects.create
            # ...but it doesn't seem to work for some reason, wrong syntax perhaps?

            upload_path = handle_uploaded_file(image_1)
            image = Image.objects.create(content_object=room, image=upload_path)
            return HttpResponseRedirect(room.get_absolute_url())
    else:
        form = form_class()
    context = {'form': form, }
    return direct_to_template(request, template, extra_context=context)


推荐答案

您不必使用Image类。建议 DZPM 将图像字段转换为ImageField。您还需要对视图进行一些更改。

You don't have to use the Image class. As DZPM suggested, convert the image field to an ImageField. You also need to make some changes to the view.

而不是使用上传处理程序,您可以使用上传的数据创建一个Image对象,并将Image对象附加到

Instead of using an upload handler, you can create a Image object with the uploaded data and attach the Image object to the Room object.

要保存Image对象,您需要在视图中执行以下操作:

To save the Image object you need to do something like this in the view:

from django.core.files.base import ContentFile

if request.FILES.has_key('image_1'):
    image_obj = Image()
    image_obj.file.save(request.FILES['image_1'].name,\
                        ContentFile(request.FILES['image_1'].read()))
    image_obj.save()
    room_obj.image_set.create(image_obj)
    room_obj.save()

另外,我想,而不是GenericRelation,你应该使用一个ManyToManyField,在这种情况下,添加一个图像到一个房间的语法将会稍微改变。

Also, I think instead of the GenericRelation, you should use a ManyToManyField, in which case the syntax for adding an Image to a Room will change slightly.

这篇关于将通用图像字段添加到django中的ModelForm中的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆