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

Django custom widget, populate from another table (similar to inlines)

我正在编写一个用于多张图片上传的自定义小部件。我的模型是:

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__'

所以问题是,我在房间模型中没有画廊字段,但我想使用小部件来管理存储在图片中的图片 table 类似于通过内联管理数据的方式。

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

谢谢

我认为您使用了错误的方法来解决您的问题。 Widget 应该只负责显示数据,而不应该关心数据来自哪里。您的 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)

希望这能解决您的问题