I have an inlineformset_factory that is a group of ShoppingListItemForm
View:
class ShoppingListItemForm(ModelForm):
@property
def __name__(self):
return self.__class__.__name__
def __init__(self, *args, **kwargs):
if kwargs.get('instance'):
theList = kwargs['instance']
self.fields['category'] = forms.ChoiceField(choices=[(cat.id, cat.name) for cat in ListItemCategory.objects.filter(shoppinglist__id=theList.id)])
return super(ShoppingListItemForm, self).__init__(self, *args, **kwargs)
class Meta:
model = ShoppingListItem
fields = ('item', 'brand', 'quantity', 'current', 'category', 'size', )
@login_required
def shoppinglist(request, shoppinglist_id, pod_id):
profile = request.user.get_profile()
shoppinglist = get_object_or_404(ShoppingList, pk=shoppinglist_id)
ListFormSet = inlineformset_factory(ShoppingList, ShoppingListItem, form=ShoppingListItemForm, extra=1, can_delete=True)
myForms = ListFormSet(instance=shoppinglist)
...This works great, except 'category' is a foreign key of ShoppingListItem, and I need to filter the 'category' options offered on my form to only those which are related to ListItemCategory by 'shoppinglist'. 'shoppinglist' is a foreign key of both ListItemCategory and ShoppingListItem.
Models:
class ListItemCategory(models.Model):
name = models.CharField(max_length=30, blank=True, null=True)
shoppinglist = models.ForeignKey(ShoppingList)
class ShoppingListItem(models.Model):
shoppinglist = models.ForeignKey(ShoppingList)
category = models.ForeignKey(ListItemCategory, blank=True, null=True, default = None)
item = models.CharField(max_length=200, blank=True, null=True)
class ShoppingList(models.Model):
name = models.CharField(max_length=30, blank=True, null=True, default="Pod List")
...I think there is no need to pass in the 'shoppinglist' as an extra argument, as it is passed as the instance of the form, but with this initialization added, my rendered template has nothing at all in the formset.
Any further advice?
Your issue is that you're not "initializing" the variable shoppinglist_id
in your form def init
Try this:
class ShoppingListItemForm(ModelForm):
class Meta:
model = ShoppingListItem
fields = ('item', 'brand', 'quantity', 'current', 'category', 'size', )
def __init__(self, *args, **kwargs):
shoppinglist_id = kwargs.pop('shoppinglist_id', None)
super(ShoppingListItemForm, self).__init__(*args, **kwargs)
self.fields['category'].queryset = ListItemCategory.objects.filter(shoppinglist__id=shoppinglist_id)
And you should edit also how to initialize the form:
ListFormSet = inlineformset_factory(ShoppingList, ShoppingListItem, form=ShoppingListItemForm(shoppinglist_id=shoppinglist.id), extra=1, can_delete=True)
The changes made are the next ones:
shoppinglist_id
as a kwarg argument...ShoppingListItemForm(shoppinglist_id=shoppinglist.id)
Get the kwarg argument in your form
def __init__(self, *args, **kwargs):
shoppinglist_id = kwargs.pop('shoppinglist_id', None)