I have models:
from django.contrib.auth.models import User
class ProductToRecipe(models.Model):
recipe = models.ForeignKey(Recipe)
product = models.ForeignKey(Product)
count = models.IntegerField()
class Product(models.Model):
name = models.CharField()
creator = models.ForeignKey(User)
Where ProductToRecipe model is part of modelformset_factory (call from views.py):
ProductRecipeFormSet = modelformset_factory(ProductToRecipe,
form=ProductRecipeForm)
forms.py:
class ProductRecipeForm(ModelForm):
class Meta():
model = ProductToRecipe
fields = ['product', 'count']
How can I add filter in ProductRecipeForm so that only products that have product.creator==request.user are added to the product=ForeignKey(Product) field?
You can pass a custom queryset as a parameter to the formset class (not the factory call), See changing the queryset in the docs.
This idea sounds interesting, but how can I setup queryset, which will have filter on it’s ForeignKey Field? As I understand, I should do in views something like:
recipe = get_object_or_404(Recipe, pk=recipe_id, author=request.user)
products = ProductToRecipe.objects.filter(recipe=recipe,
product.creator=request.user)
ProductRecipeFormSet = modelformset_factory(ProductToRecipe,
form=ProductRecipeForm)
product_formset = ProductRecipeFormSet(queryset=products)
But in Django I can’t setup field of ForeignKey in way product.creator=request.user.
I thought that I can do something like
recipe = get_object_or_404(Recipe, pk=recipe_id, author=request.user)
products = ProductToRecipe.objects.filter(recipe=recipe)
ProductRecipeFormSet = modelformset_factory(ProductToRecipe,
form=ProductRecipeForm)
user_products = Product.objects.filter(creator=request.user)
product_formset = ProductRecipeFormSet(queryset=products,
user_products=user_products)
And than in forms.py write:
class ProductRecipeForm(ModelForm):
class Meta():
model = ProductToRecipe
fields = ['product', 'count']
def __init__(self, user_products, *args, **kwargs):
super().__init__(*args, **kwargs)
self.fields["product"].queryset = user_products
But I don’t know how properly pass user_products parameter
I found on StackOverflow python - How do I filter ForeignKey choices in a Django ModelForm? - Stack Overflow solution in the same problem but with formset_factory. However, I didn’t understand how to do the same in modelformsets
Ok, I think I may have been confused with your original question.
Let me try to rephrase this for clarity.
You are creating a Formset of ProductToRecipe.
This means you are going to be rendering multiple instances of a form to create / update the ProductToRecipe models.
In each of those model instances there is a field named product
. It (by default) is going to render as a ModelSelect field, allowing the choice of one instance of Product
.
The question here is that you’re trying to limit the list of Product
for the ModelSelect field.
The list of Product
to be available for product
is going to be the same across all instances of the ProductToRecipe
form.
Do I finally have this right? (Would you say this is an accurate phrasing?)
1 Like
Yes, that’s what I want to do. Sorry for bad phrasing of original question
Nope, no worries - I just wanted to ensure I understood the situation.
For that situation you have the form_kwargs
parameter that you can use in the model formset construction call (in your situation above, product_formset = ProductRecipeFormSet(...)
). Anything you supply in that dict gets passed through as parameters to the form __init__
method.
See Passing custom parameters to formset forms.
Since you’re wanting to pass the same information to all the instances, you can ignore the references to get_form_kwargs
.
1 Like
This is what I really needed. It turned out to be much easier than I thought. Thank you so much for your help!