How to implement edit-form with Django formset? - django

I implemented a django-form with a formset. When I create a new object it works. But I faced to a problem with editing form when I don't change formset data (only data outside formset). Formset raises errors: id requeired. If I mark formset fields to delete and then add new fields it works too. Please, explain me what's going wrong and how to solve this problem. Thanks!
My formset:
IngredientsFormSet = forms.inlineformset_factory(
Recipe,
RecipeIngredientsDetails,
fields="__all__",
can_delete=True,
min_num=2,
max_num=50,
extra=0,
)
And my view-function:
def recipe_edit(request, recipe_id=None):
if recipe_id:
recipe = get_object_or_404(Recipe, id=recipe_id)
else:
recipe = Recipe()
if request.method == "POST":
form = RecipeCreateForm(data=request.POST, files=request.FILES)
formset = IngredientsFormSet(data=request.POST,
prefix=INGREDIENT_FORMSET_PREFIX)
if form.is_valid() and formset.is_valid():
recipe = form.save(commit=False)
recipe.author_id = request.user.id
recipe.save()
form.save_m2m()
formset.instance = recipe
formset.save()
return redirect(reverse_lazy("index"))
context = {"form": form, "formset": formset}
return render(request, template_name="recipe-create.html",
context=context)
form = RecipeCreateForm(instance=recipe)
formset = IngredientsFormSet(
instance=recipe,
prefix=INGREDIENT_FORMSET_PREFIX,
)
context = {
"form": form,
"formset": formset,
}
return render(request, context=context, template_name="recipe-create.html")
Update:
When I set value of the hidden form-field with id="ingredient-INITIAL_FORMS" to zero the errors disappear. This value is the initial number of forms in formset, the question is how to validate them.
I suppose that problems are related to the management_form feature, but what is exact?

Related

Django- how to save formset model

I have the following view code
def edit_pal(request,pal_id):
pals=palabout.objects.get(id=pal_id)
form2=editpalForm(request.POST or None,instance=pals)
RecipeIngredientFormset = modelformset_factory(palabout, form=editspalForm,extra=0)
formset = RecipeIngredientFormset(request.POST or None,prefix=pals)
context={
"formset": formset,
"form2":form2,
"pals":pals
}
if request.method == 'POST':
if form2.is_valid() and formset.is_valid():
parent = form2.save(commit=False)
parent.save()
for form in formset:
child = form.save(commit=False)
child.recipe = parent
child.save()
context['message']='Data Saved'
return redirect('hod:manage_pal')
return render(request,"edit-pal.html",context)
I remove formset.is_validso it's working but it's not working when i added more for used formset.is_validso why isn't saving file or details show? Can anyone help this?
I think you need to only redirect if the forms are valid so try this view:
from django.shortcuts import get_object_or_404
def edit_pal(request,pal_id):
pals=get_object_or_404(palabout,id=pal_id)
if request.method == 'POST':
form2=editpalForm(request.POST,instance=pals)
RecipeIngredientFormset = modelformset_factory(palabout, form=editspalForm,extra=0)
formset = RecipeIngredientFormset(request.POST,prefix=pals)
if form2.is_valid() and formset.is_valid():
parent = form2.save(commit=False)
parent.save()
for form in formset:
child = form.save(commit=False)
child.recipe = parent
child.save()
context['message']='Data Saved'
return redirect('hod:manage_pal')
else: # if the form is not valid
return redirect("hod:some_error_page")
else: # GET request
RecipeIngredientFormset = modelformset_factory(palabout, form=editspalForm,extra=0)
formset = RecipeIngredientFormset(prefix=pals)
context={
"formset": formset,
"form2":editpalForm(instance=pals),
"pals":pals
}
return render(request,"edit-pal.html",context)

Save formset in Django returns None model

I've a problem with my formset. When I submit the formset, the models are not saved and displayed as None. I don't understand why, can somebody light me ?
There is no problem in the template nor the urls.py. I get this within my log console:
See image
Here is my code:
// views.py
def classroom_call_the_roll(request, class_id):
classroom = Classroom.objects.get(pk=class_id)
students = classroom.students.all()
queryset = Attendance.objects.none()
AttendanceFormset = modelformset_factory(
model=Attendance,
form=AttendanceForm,
can_delete=False,
extra=len(students)
)
if request.method == 'POST':
formset = AttendanceFormset(
request.POST,
queryset=queryset,
initial=[{'student': student} for student in students]
)
for form in formset.forms:
instance = form.save(commit=False)
print(instance)
else:
formset = AttendanceFormset(
queryset=queryset,
initial=[{'student': student} for student in students]
)
return render(
request,
'highschool/attendance/classroom_attendance_create.html',
{
'formset': formset
}
)
i see you have set commit=False in form.save call. If you do this, you have to save the instance yourself by calling
instance.save()
You should save the model manually. To do that, you should add instance.save()

Django Issue Template Does Not Exist at /deals/

I am new Django user. When I run program in Django I got this error please help.
Template Does Not Exist at /deals/
{'form': <DealsForm bound=False, valid=Unknown, fields=(name;pages;email)>}
view.py
class DealsForm(ModelForm):
class Meta:
model = Book
fields = ['name','pages','email']
def deals(request):
products = Product.objects.all()
form = DealsForm()
context = {'products': products}
if request.method == "POST":
form = DealsForm(request.POST, request.FILES)
if form.is_valid():
form.save()
return redirect('products/deals')
else:
form = DealsForm()
return render('products/deals.html',{'form': form}, context_instance=context)
Your mistake was the arguments to the render function, it waits parameters like
render(request, 'name_of_template.html', context_dict)
Also, check your form variable it must be inside of the context dictionary, try adding it this way before pass it to render:
context['form'] = form
These things should work now.

Filter Objects in a Django Formset

I am using inlineformset_factory to generate a formset as so:
FormSet = inlineformset_factory(Model1, Model2, extra=0)
if request.method =="POST":
formset = FormSet(request.POST, instance=model1_object)
if formset.is_valid():
formset.save()
return HttpResponseRedirect( reverse-blah )
else:
formset = PupsFormSet(instance=model1_object,)
return render_to_response("template.html", {"formset":formset, 'model1_object':model1_object},context_instance=RequestContext(request))
I have two questions
How can i restrict the Model2 objects so that not all applicable objects are present, but only a filtered subset?
Does anyone have any example code for using class-based views with formsets?
Updated with functioning code answering question #1
FormSet = inlineformset_factory(Model1, Model2, extra=0)
if request.method =="POST":
formset = FormSet(request.POST, instance=model1_object, queryset=Model2.objects.filter(foo=bar))
if formset.is_valid():
formset.save()
return HttpResponseRedirect( reverse-blah )
else:
formset = PupsFormSet(instance=model1_object, queryset=Model2.objects.filter(foo=bar))
return render_to_response("template.html", {"formset":formset, 'model1_object':model1_object},context_instance=RequestContext(request))
would this help? https://docs.djangoproject.com/en/dev/topics/forms/modelforms/#changing-the-queryset
basically, try using queryset kwarg when you create your formset.

Saving modelform - won't validate

I'm doing something wrong here, but I can't find it.
I'm using a model form:
class ArtistInfo(ModelForm):
class Meta:
model = Onesheet
fields = (
'name',
'genre',
'location',
'biography',
)
And trying to save the data entered for an existing record.
def edit_artist_info(request, onesheet):
onesheet = Onesheet.objects.get(id = onesheet)
if request.method == 'POST':
form = ArtistInfo(request.POST, instance=onesheet)
if form.is_valid():
test = form.save(commit=False)
test.save()
HttpResponseRedirect('/')
form = ArtistInfo(instance=onesheet, label_suffix='')
variables = RequestContext(request, {
'onesheet':onesheet,
'form': form,
})
return render_to_response('edit_artist_info.html', variables)
But it's not saving. It just reloads the page with whatever the user changed, but if you actually refresh the page (grabbing the value from the DB), it's the old value.
Any ideas? If it's because the form isn't actually validating, I dont know why it's not validating.
try just
if request.method == 'POST':
form = ArtistInfo(request.POST, instance=onesheet)
if form.is_valid():
form.save()
return HttpResponseRedirect('/')
You were missing the return statement in your code, and the extra save() was unnecessary