I want to keep the form fields preserved after submitting the form. I can preserve all the fields except the checked checkboxes
Here is my form action view:
def student_submit_info(request):
form_values = {}
if request.method == 'POST':
form = StudentForm(request.POST)
print form.is_valid()
form_values = getDetails(request)
if form.is_valid():
print request.user.username
student = Student.objects.get(user=request.user)
// saving student to DB
saveDetails(request, student, form_values)
return render_to_response('student.html', form_values, context_instance=RequestContext(request))
def getDetails(request):
#fetch input data
form_values = {}
form_values['first_name'] = request.POST['first_name']
form_values['last_name'] = request.POST['last_name']
form_values['skills'] = request.POST.getlist('skills[]')
return form_values
I would want to preserve skills (checkbox), here's a part of my template
skill1<input type="checkbox" name="skills[]" checked value="skill1"/>
skill2<input type="checkbox" name="skills[]" value="skill2"/>
skill3<input type="checkbox" name="skills[]" value="skill3"/>
You should make a custom django Forms to handle easily forms, example of a post view:
def post_view(request):
form = MyForm(request.POST)
if form.is_valid():
do_something()
render(request, 'your_temp', {'MyForm': MyForm'})
With this kind of snippet, data in form will always be those sent.
You can override is_valid() for empty skill checkboxes.
Perhaps, use CBV's and ModelForms to make the process simpler.
Combine a listview (or similar) and add your form via context.
Then in get_context_data of your CBV:
form_values = {}
#Simpler code below for accessing post dictionary
for key, value in self.request.POST.items():
if value == 'on':
form_values[key] = value
context = super().get_context_data(**kwargs)
# You need to add form_values to make it accessible in the forms.py
context['form'] = YourFormName(form_values)
Then, in your forms.py (I'm hoping you use modelforms):
def __init__(self, filters, *args, **kwargs):
super(YourFormName, self).__init__(*args, **kwargs)
if len(form_values) > 0:
for field_name in self.fields:
if field_name in filters:
self.fields[field_name].widget = forms.CheckboxInput(attrs={'checked': True})
I hope this helps.
Related
So, How can I update some Model Fields automatic, without the user having to input the values?
In Models:
class Url(models.Model):
long_url = models.CharField("Long Url",max_length=600)
short_url = models.CharField("Short Url",max_length=7)
visits = models.IntegerField("Site Visits",null=True)
creator = models.ForeignKey(CurtItUser,on_delete=models.CASCADE,null=True)
def __str__(self):
return self.short_url
In Views:
def home(request):
"""Main Page, Random Code Gen, Appendage Of New Data To The DB"""
global res,final_url
if request.method == 'POST':
form = UrlForm(request.POST)
if form.is_valid():
res = "".join(random.choices(string.ascii_uppercase,k=7))
final_url = f"127.0.0.1:8000/link/{res}"
form.save()
redirect(...)
else:
form = UrlForm
return render(...)
Sow how can for exapmle set from my view the value of short_url to final_url ???
You can get the data you need from the form.
you need to get the specific instance first, then you can use that instance to save values from the form.
And do not forget to save!
url_instance = get_object_or_404(Url, pk=pk)
url_instance.short_url = form.cleaned_data['short_url']
url_instance.long_url = form.cleaned_data['long_url']
url_instance.visits = form.cleaned_data['visits']
url_instance.save()
You can find more detailed infromations in the Django Documentation.
I'm new at Python & Django and currently struggling right now.
I created an update/edit form with Django Model forms, but it just doesn't prepopulate the form fields and post it to the database at the same time.
I think the problem lies in form = AdvertForm(request.POST or None, request.FILES or None, instance=form).
Without request.POST or None, request.FILES or None, it does prepopulate the fields but won't update the data to database.
Here's my views.py:
def update_advert(request, id):
if not request.user.is_authenticated():
return render(request, 'forum/login.html')
else:
form = get_object_or_404(Advert, pk=id)
if request.method == 'POST':
form = AdvertForm(request.POST or None, request.FILES or None, instance=form)
if form.is_valid():
form = form.save(commit=False)
form.user = request.user
form.save()
return redirect('forum:user_account')
else:
form = AdvertForm(instance=form)
context = {'form': form}
return render(request, 'forum/update_advert.html', context)
In the moment it looks like this, when I try to open the update form:
opening the form --> not prepopulated :(
According to https://docs.djangoproject.com/en/dev/ref/forms/api/#dynamic-initial-values, you can use the initial attribute when instantiating forms in order to prepropulate your forms.
def update_advert(request, id):
if not request.user.is_authenticated():
return render(request, 'forum/login.html')
else:
advert_obj = get_object_or_404(Advert, pk=id)
if request.method == 'POST':
form = AdvertForm(request.POST or None, request.FILES or None, instance=advert_obj)
if form.is_valid():
form.save()
return redirect('forum:user_account')
else:
# Prepopulation happens here:
data = {"some_field": advert_obj.some_val} # Insert all the values of advert_obj here and their field names as keys.
form = AdvertForm(initial=data)
context = {'form': form}
return render(request, 'forum/update_advert.html', context)
In your AdvertForm, put this code:
class AdvertForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
self.request = kwargs.pop('request', None)
super(AdvertForm, self).__init__(*args, **kwargs)
def save(self, commit=True):
instance = super(AdvertForm, self).save(commit=False)
instance.user = self.request.user
if commit:
instance.save()
return instance
The overriding save method simply does what you were doing in the views to link up the request.user to the instance, however I have placed that code in the form class to keep your views simple.
Also, I can see one confusing (but not vital) issue - you have mixed up the variable names.
When calling form = get_object_or_404(Advert, pk=id), this should return to a variable name such as advert or something similar. Not form as that can be confusing as we are returning a model object not a form. Similarly, form.save(commit=False) returns an "instance" not a model form. This won't solve your problem but should be pointed out for more clarification on what exactly is being returned and how you should then name your variables.
Im trying to get the value form a post in django but it pass an empty field `def PersonEmail(request):
Im trying to get the value form a post in django but it pass an empty field `def PersonEmail(request):
if request.method == "POST":
form1 = PersonForm(request.POST, prefix="form1")
form2 = EmailForm(request.POST, prefix="form2")
name = form2['email'].value
return HttpResponse(name)
else:
form1 = PersonForm()
form2 = EmailForm()
return render(request, 'CreatePersonEmail.html', locals())`
but when i separate them i.e.
Im trying to get the value form a post in django but it pass an empty field `def PersonEmail(request):
if request.method == "POST":
# form1 = PersonForm(request.POST, prefix="form1")
form2 = EmailForm(request.POST, prefix="form2")
name = form2['email'].value
return HttpResponse(name)
else:
form1 = PersonForm()
form2 = EmailForm()
return render(request, 'CreatePersonEmail.html', locals())`
it gives me the value of the field.
Why? and how can i make it to obtain the values of both forms fields?
Basically, you're doing it wrong.
Firstly, you need to check if the form is valid. Users could type any crap in, you don't want to let them do that:
if request.method == "POST":
form = MyForm(request.POST)
if form.is_valid():
# Now you can access the fields:
name = form.cleaned_data['name']
If the form isn't valid, just pass it back to render() and it will show the errors.
Also, don't do this:
return render(request, 'CreatePersonEmail.html', locals())`
Build your context dictionary properly, don't use locals(), it's hacky and you pollute your context.
So a full view might look like this (taken from django docs and changed a bit:
def get_name(request):
# 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 = NameForm(request.POST)
# check whether it's valid:
if form.is_valid():
name = form.cleaned_data['name']
return render(request, 'some_page.html', {'name': name})
# if a GET (or any other method) we'll create a blank form
else:
form = NameForm()
return render(request, 'name.html', {'form': form})
You need to use the prefix both times you instantiate the forms; both on GET and on POST.
Also, you get values from the form's cleaned_data dict, not from the field.
Some of my mistakes here are to do with my very limited python knowledge as much as anything, however I have been searching for half a day now.
class AssignmentForm(forms.ModelForm):
def __init__(self, *args, **kwargs, m_id):
super(AssignmentForm, self).__init__(*args, **kwargs)
# Making name required
self.fields['title'].required = True
self.fields['title'].help_text = "Title Required"
self.fields['description'].required = True
self.fields['description'].help_text= "Description Optional"
self.fields['module_id'].required = False
self.fields['module_id'] = m_id
class Meta:
# Provide an association between the ModelForm and a model
model = Assignment
fields = ('title', 'description', 'module_id')
This is my view
def add_assignment(request, m_id):
template = loader.get_template('add_assignment.html')
if request.method == 'POST':
form = AssignmentForm(request.POST, m_id)
if form.is_valid():
form.save(commit=True)
return module(request, m_id)
else:
print form.errors
else:
form = AssignmentForm()
# Bad form (or form details), no form supplied...
# Render the form with error messages (if any).
context = RequestContext(request,
{
'form':form,
})
return HttpResponse(template.render(context))
And this my URL mapping
url(r'^courses/(?P<m_id>\d+)/new/$', add_assignment, name='add_assignment'),
I'm currently getting an error because I mustn't be meant to pass values into init however I don't know how else to get the 'module_id' in.
Thanks again and I realise I might be structuring the whole thing terribly.
I have a model form with custom constructor. It checks if a file is required and if false, it deletes the file field. It also has two hidden fields, which I initialize at my views. The form class is as follows:
class SubmitTask(forms.ModelForm):
task = forms.ModelChoiceField(queryset=Task.objects.all(), widget=forms.HiddenInput())
student = forms.ModelChoiceField(queryset=UserProfile.objects.all(), widget=forms.HiddenInput())
def __init__(self, file_required=False, *args, **kwargs):
super(SubmitTask, self).__init__(*args, **kwargs)
if file_required is True:
file = forms.FileField(
label='Select a file',
help_text='max: 2.5 MB'
)
else:
del self.fields['file']
class Meta:
model = Submission
exclude = ('date_submitted',)
My problem is that the hidden fields are populated when I initialize the form (I have confirmed that its values are indeed initialized by viewing the HTML code). However, the values of the hidden fields are not populated during POST request. I have confirmed during POST request that the form is indeed bound and I also confirmed on Firebug that POST also contains the task and student values. This is the involved method in my views.py
def view_task(request, id):
task = Task.objects.get(pk=id)
profile = request.user.get_profile()
data = {}
data['classroom'] = task.get_classroom()
data['description'] = task.get_description()
teacher_classrooms = Classroom.objects.filter(teacher=profile)
teacher_tasks = Task.objects.filter(classroom__in=teacher_classrooms)
if not submission and task not in teacher_tasks:
form = SubmitTask(file_required=task.file_required, initial={'task':task.pk, 'student':profile.pk})
data['form'] = form
if request.method == 'POST':
form = SubmitTask(request.POST, request.FILES)
if form.is_valid():
form.save()
return render_to_response('classrooms/view_task.html',
data, context_instance=RequestContext(request))
Your view function looks incorrect to me:
Where does the submission variable come from, when initializing the posted form you are missing the file_required parameter and the form processing should perhaps be reorganized to something like:
if request.method == 'POST':
form = SubmitTask(task.file_required, request.POST, request.FILES)
...
else:
form = SubmitTask(task.file_required, ...)
data['form'] = form