How to write an update view with formset_factory - django

I love how I can pass an instance to a form and it will populate it on a page. The trouble I am having is with formset_factory. I am trying to use query_set...
def classroom_update(request, pk):
classroom = get_object_or_404(Classroom, pk=pk)
students = classroom.student_set.all()
# Empty formset forms should be required
class RequiredFormSet(BaseFormSet):
def __init__(self, *args, **kwargs):
super(RequiredFormSet, self).__init__(*args, **kwargs)
for form in self.forms:
form.empty_permitted = False
#StudentFormSet = inlineformset_factory(Classroom, Student)
StudentFormSet = formset_factory(StudentForm, max_num=100, formset=RequiredFormSet)
if request.method == 'POST': # If the form has been submitted...
classroom_form = ClassroomForm(request.POST)
student_formset = StudentFormSet(request.POST, request.FILES)
if classroom_form.is_valid() and student_formset.is_valid():
classroom = classroom_form.save(commit=False)
classroom.user = request.user
classroom.save()
for form in student_formset.forms:
student = form.save(commit=False)
student.classroom = classroom
student.save()
return HttpResponseRedirect('/') # Redirect to a 'success' page
else:
classroom_form = ClassroomForm(instance=classroom)
student_formset = StudentFormSet(query_set=students)
# For CSRF protection
# See http://docs.djangoproject.com/en/dev/ref/contrib/csrf/
c = {'classroom_form': classroom_form,
'student_formset': student_formset,
}
c.update(csrf(request))
return render_to_response('reports/modify_classroom.html', c)
EDIT: Here is the error message...
formset_factory() got an unexpected keyword argument 'query_set'
Apparently I don't know how to use query_set...

Related

Cannot assign "<QuerySet [<Books: Utengano-ut/23>]>": "TeacherIssue.book_id" must be a "Books" instance

I wanted to implement Select2MultipleWidget but I have not managed to succeed in the view. This is what I have but it gives a value error
raise ValueError(
ValueError: Cannot assign "<QuerySet [<Books: Utengano-ut/23>]>": "TeacherIssue.book_id" must be a "Books" instance.
My view
def new_issue(request,pk):
if request.method == 'POST':
form = IssueForm(request.POST,school= request.user.school,pk=pk,issuer = request.user)
if form.is_valid():
print("Form valid")
try:
book = request.POST.getlist('book_id')
#book = form.cleaned_data['book_id'].id
for item in book:
form.cleaned_data[item].id
form.save(commit=True)
books = Books.objects.filter(id__in = book).select_related('subject')
for book.id in books:
Books.Claimbook(book)
return redirect('all_borrowed_teacher', borrowed=borrowed)
except Exception as e:
return redirect('teachers')
else:
form = IssueForm(school= request.user.school,pk=pk,issuer = request.user)
return render(request, 'lib.html', {'form': form})
This is the form
class IssueForm(forms.ModelForm):
def __init__(self,*args, pk, **kwargs):
super(IssueForm, self).__init__(*args, **kwargs)
self.fields["book_id"] = forms.ModelMultipleChoiceField(queryset=Books.objects.all(), widget=Select2MultipleWidget)
class Meta:
model = TeacherIssue
fields = ['book_id']

Instance of djaform not updating

I have the next form in Django:
class Medical(forms.ModelForm):
worker= forms.ModelChoiceField(
queryset=Worker.objects.none(),
empty_label=None,
widget=forms.Select(attrs={'class': 'form-control'})
)
description=forms.CharField(
widget=forms.Textarea(attrs={'class': 'form-control'})
)
upload=forms.FileField(
widget=forms.FileInput(attrs={'class': 'form-control'})
)
class Meta:
model = Medical_Issue
fields = (
'worker',
'description',
'upload',
)
def __init__(self, *args, **kwargs):
user_id = kwargs.pop('user_id')
method=kwargs.pop('method')
super().__init__(*args, **kwargs)
self.fields['worker'].queryset = Worker.objects.filter(user_id=user_id)
def save(self, commit=True):
m = super(Medical, self).save(commit=False)
m.worker=self.cleaned_data['worker']
m.description=self.cleaned_data['description']
m.upload=self.cleaned_data['upload']
if commit:
m.save()
return m
And following views:
def medical_list(request):
worker=Worker.objects.filter(user_id=request.user.id).get()
issues=Medical_Issue.objects.filter(worker=worker.id).order_by('-created_at')
return render(request,'medical_list.html', {'medical_issues':issues})
def medical_add(request):
print(request.user.id)
if request.method == "POST":
form = Medical(request.POST,request.FILES,user_id=request.user, method= 'ADD')
if form.is_valid():
form.save()
return redirect('medical_list')
else:
form = Medical(user_id=request.user, method= 'ADD')
return render(request, 'medical_add.html', {'method':'ADD','form': form})
def medical_edit(request,id_issue):
worker=Worker.objects.get(user_id=request.user)
issues=Medical_Issue.objects.filter(worker=worker).order_by('-created_at')
issue= Medical_Issue.objects.get(id=id_issue)
if request.method == 'GET':
form = Medical(user_id=worker.user_id,instance=issue, method= 'EDIT')
else:
form = Medical(request.POST, request.FILES, user_id=worker.user_id, method= 'EDIT')
if form.is_valid():
form.save()
return redirect('medical_list')
return render(request,'medical_add.html', {'method':'EDIT','form': form})
Main probles is when adding, it saves record just fine, but when editing, it is creating a new instance of the issue.
I´m trying to make it modifying save method on form, but maybe it´s not the right approach? With thata said, I have tried to add an id field to the form, but same results from this
Thanks
I suspect that you don't pass the correct instance value to the form in your medical_edit view:
issue= Medical_Issue.objects.get(id=id_issue)
if request.method == 'GET':
form = Medical(
user_id=worker.user_id,
instance=issue, # <-- issue or parte?
method='EDIT'
)
UPDATE
It should also include the instance argument in the POST method.
if request.method == 'GET':
# ...
else:
form = Medical(
request.POST,
request.FILES,
instance=issue, # <--
user_id=worker.user_id,
method= 'EDIT'
)

Django Form : after correctly submitting form I got this: "this field is required"

I've a category and I've added a form for user in each category.
So I've two fields to fill and after filling them correctly I submit but the page reload, and nothing appears in my DB... only one error on Image field: This field required. I don't really know what's wrong here.
class Picture(models.Model):
catego = models.ForeignKey(Catego,on_delete=models.CASCADE,related_name="catego_pictures")
user = models.ForeignKey(User, blank=True, null=True,on_delete=models.CASCADE,related_name='user_pictures')
image = models.ImageField(upload_to='nutriscore/')
pictureoption = models.CharField(max_length=20,choices=Pictureoption.choices,default=Pictureoption.HOME,)
publishing_date = models.DateField(auto_now_add=True)
class CreatePictureForm(forms.ModelForm):
def __init__(self,*args,**kwargs):
super(CreatePictureForm, self).__init__(*args,**kwargs)
self.helper = FormHelper()
self.helper.form_method="post"
self.helper.layout = Layout(
Field("image",css_class="single-input"),
Field("pictureoption",css_class="single-input"),
)
self.helper.add_input(Submit('submit','Upload a pic',css_class="single-input textinput textInput form-control"))
class Meta:
model = Picture
fields = [
'image',
'pictureoption',
]
def __str__(self):
return self.catego.name
views.py
#login_required(login_url='/cooker/login')
def catego(request, slug):
catego = Catego.objects.get(slug=slug)
context = {
'catego': catego
}
# if this is a POST request we need to process the form data
if request.method == 'POST':
# create a form instance and populate it with data from the request:
form = CreatePictureForm(request.POST)
# check whether it's valid:
if form.is_valid():
form.instance.catego = self.object
form.instance.user = self.request.user
form.save()
return HttpResponseRedirect(request.META.get('HTTP_REFERER'))
else:
form = CreatePictureForm()
context['form'] = form # add `form` to the context
return render(request, 'post_catego.html', context)
here is the answer
#login_required(login_url='/cooker/login')
def catego(request, slug):
catego = Catego.objects.get(slug=slug)
context = {
'catego': catego
}
# if this is a POST request we need to process the form data
if request.method == 'POST':
# create a form instance and populate it with data from the request:
form = CreatePictureForm(request.POST, request.FILES)
# check whether it's valid:
if form.is_valid():
form.instance.catego = catego
form.instance.user = request.user
form.save()
return HttpResponseRedirect(request.META.get('HTTP_REFERER'))
else:
form = CreatePictureForm()
context['form'] = form # add `form` to the context
return render(request, 'post_catego.html', context)

create help text for a field dynamically

I have my response form and view like this
class ResponseForm(ModelForm):
class Meta:
model = ResponseModel
exclude = ('author', 'title','submit_count')
# help_texts = {
# 'ans1': user.q1.value,
# }
#login_required
def ResponseFormView(request):
if request.method == "POST":
form = ResponseForm(request.POST)
if form.is_valid():
submission = form.save(commit=False)
submission.author = request.user
submission.save()
return render(request, 'thanks.html', {})
else:
form = ResponseForm()
return render(request, 'response_tem.html', {'form': form})
I want the help text for 'ans1' field to be the value of q1 field of request.user. How do I do it?
You can do it like this:
class ResponseForm(ModelForm):
def __init__(self, *args, **kwargs):
user = kwargs.pop('user', None) # popping user from known arguments
super(ResponseForm, self).__init__(*args, **kwargs)
if user:
self.fields['ans1'].help_text = "Help Text for {}".format(user.username)
class Meta:
model = ResponseModel
exclude = ('author', 'title','submit_count')
#login_required
def ResponseFormView(request):
if request.method == "POST":
form = ResponseForm(request.POST)
if form.is_valid():
submission = form.save(commit=False)
submission.author = request.user
submission.save()
return render(request, 'thanks.html', {})
else:
form = ResponseForm(user=request.user) # passing user as known argument
return render(request, 'response_tem.html', {'form': form})
Here, in the view I am passing the request.user as known argument when I am initiating Form Class's Object (marked with comment). Then in the Form, I am catching the user sent from view and updating the field's help text.

Setting foreignkey in formsets

I am getting this error
reports_student.classroom_id may not be NULL
Here is my view. What am I doing wrong here? I think the problem is caused by setting the foreign keys. Classroom belongs to user... students belong to classroom...
def build_classroom(request):
print "building classroom"
# Empty formset forms should be required
class RequiredFormSet(BaseFormSet):
def __init__(self, *args, **kwargs):
super(RequiredFormSet, self).__init__(*args, **kwargs)
for form in self.forms:
form.empty_permitted = False
StudentFormSet = formset_factory(StudentForm, max_num=100, formset=RequiredFormSet)
if request.method == 'POST': # If the form has been submitted...
classroom_form = ClassroomForm(request.POST)
student_formset = StudentFormSet(request.POST, request.FILES)
if classroom_form.is_valid() and student_formset.is_valid():
classroom = classroom_form.save(commit=False)
classroom.user = request.user
for form in student_formset.forms:
student = form.save(commit=False)
student.classroom = classroom
student.save()
return HttpResponseRedirect('/') # Redirect to a 'success' page
else:
classroom_form = ClassroomForm()
student_formset = StudentFormSet()
# For CSRF protection
# See http://docs.djangoproject.com/en/dev/ref/contrib/csrf/
c = {'classroom_form': classroom_form,
'student_formset': student_formset,
}
c.update(csrf(request))
return render_to_response('reports/build_classroom.html', c)
classroom = classroom_form.save(commit=False)
Since you have used commit=False on the classroom form, classroom likely doesn't have an ID value that can be assigned to student.
Save the classroom instance first (omit the commit=False).
if classroom_form.is_valid() and student_formset.is_valid():
classroom = classroom_form.save(commit=False) # So you can add FK
classroom.user = request.user # exclude("user",) in forms.py so it validates
classroom.save() # put it in the database for student
for form in student_formset.forms:
student = form.save(commit=False)
student.classroom = classroom # classroom is in the database
student.save()
return HttpResponseRedirect('/')