I am writing a custom widget for multiple image uploads. My models are:
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)
I want to create custom widget which allow multiple image upload to be shown on rooms form
This is what I tried so far:
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__'
So problem is, I don't have gallery field in room model but I want to use widget to manage pictures which is stored in picture table similar to how one can manage data through inlines.
How to get id of room which is currently edited from my widget? Or is there any other way to get related pictures?
Thanks
I believe you are using a wrong approach to your problem. Widget should only be responsible of displaying data and should not care about where that data come from. your render
method accepts a value parameter, which is used to pass data to widget, so your render
should look similar to this:
class MultyImageWidget(forms.Widget):
....
def render(self, name, value, attrs=None):
context = {
'images': value
}
return mark_safe(render_to_string(self.template_name, context))
Now we need to pass the needed Picture
queryset. We can do this via form - and that what forms are for. You provided no context and I cannot comment yet to ask for details, but I suppose you are using a view to construct this form. If it is true, let's say we have some view, then we can do it this way:
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})
....
If you are using this form with Django admin, a form has instance
attribute and you can code like this:
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)
I hope this solves your problem