Django自定义小部件,从另一个表填充(类似于内联)

时间:2015-04-02 13:40:21

标签: django django-forms django-admin django-widget

我正在为多个图片上传编写自定义小部件。我的模特是:

models.py

class Room(models.Model):
    ....
    ....

class Picture (models.Model): 
    room = models.ForeignKey(Room)
    url=models.ImageField(upload_to='slider', height_field=None, width_field=None, max_length=100)

    def __unicode__(self):
        return str(self.url)

我想创建自定义窗口小部件,允许在房间窗体上显示多个图片上传

这是我到目前为止所尝试的:

forms.py

class MultyImageWidget(forms.Widget):

    ....

    def render(self, name, value, attrs=None):
        context = {
            'images': Picture.objects.filter(room = *room_id_of_currently_edited_room*)
            # OR
            # Any another way to get set of images from pictures table
    }
    return mark_safe(render_to_string(self.template_name, context))


class RoomsForm(forms.ModelForm):

    gallery = forms.ImageField(widget=MultyImageWidget, required=False)

    class Meta:
        model = Room
        fields = '__all__'

问题是,我在房间模型中没有图库字段,但我想使用窗口小部件来管理存储在图片表中的图片,类似于如何通过内联管理数据。

如何从我的小部件获取当前编辑的房间的ID? 或者还有其他方法可以获得相关的图片吗?

由于

1 个答案:

答案 0 :(得分:0)

我相信你对你的问题使用了错误的方法。窗口小部件应该只负责显示数据,而不应该关心数据的来源。您的render方法接受一个值参数,该参数用于将数据传递到窗口小部件,因此您的render应该与此类似:

class MultyImageWidget(forms.Widget):

    ....

    def render(self, name, value, attrs=None):
        context = {
            'images': value
        }
        return mark_safe(render_to_string(self.template_name, context))

现在我们需要传递所需的Picture查询集。我们可以通过表格来做到这一点 - 以及形式是什么。您没有提供任何上下文,我还没有评论要求详细信息,但我想您正在使用视图来构建此表单。如果确实如此,我们可以说有一些观点,那么我们可以这样做:

def gallery_view(request, *args, **kwargs):
    ....
    room = # get your room (maybe you pass ID via request or via arg or kwarg)
    pictures = Picture.objects.filter(room=room) # or you can do room.picture_set.all()
    form = RoomsForm(initial={'gallery': pictures})
    ....

如果您在Django admin中使用此表单,则表单具有instance属性,您可以这样编码:

class RoomsForm(forms.ModelForm):
    gallery = forms.ImageField(widget=MultyImageWidget, required=False)

    class Meta:
        model = Room
        fields = '__all__'

    def __init__(self, *args, **kwargs):
        super(RoomsForm, self).__init__(*args, **kwargs) # you may omit parameters to super in python 3
        if self.instance:
            self.fields['gallery'].initial = Picture.objects.filter(room=self.instance)

我希望这能解决你的问题