Flask submit on nested form - python

I have a multistep form like this:
{{ f.begin_form(form) }}
{% if step == "input_student_email" %}
<form action="{{ url_for('operator.add_schedule') }}" method="get">
{{ f.render_field(form.student_email) }}
<input type=hidden name="step" value="available_course">
<input type="submit" value="Check available course">
</form>
{% elif step == "available_course" %}
<form action="{{ url_for('operator.add_schedule') }}" method="get">
{{ f.render_field(form.course_name) }}
<input type=hidden name="step" value="type_of_class">
<input type="submit" value="Check type of class">
</form>
{% elif step == "type_of_class" %}
<form action="{{ url_for('operator.add_schedule') }}" method="get">
{{ f.render_field(form.type_of_class) }}
<input type=hidden name="step" value="input_schedule">
<input type="submit" value="Input Schedule">
</form>
{% elif step == "input_schedule" %}
<form action="{{ url_for('operator.add_schedule') }}" method="get">
{{ f.render_field(form.schedule_month) }}
{{ f.render_field(form.schedule_day) }}
{{ f.render_field(form.start_at) }}
{{ f.render_field(form.end_at) }}
<input type=hidden name="step" value="input_teacher_email">
<input type="submit" value="Check Teacher">
</form>
{% elif step == "input_teacher_email" %}
<form action="{{ url_for('operator.add_schedule') }}" method="get">
{{ f.render_field(form.teacher_email) }}
<input type="submit" value="Submit">
</form>
{% endif %}
{{ f.end_form() }}
and here is the route:
#operator.route('/add-schedule', methods=['GET', 'POST'])
def add_schedule():
form = ScheduleForm()
if "step" not in request.form:
return render_template('manipulate-schedule.html', form=form, step="input_student_email")
elif request.form["step"] == "available_course":
session['student_email'] = form.student_email.data
return render_template('manipulate-schedule.html', form=form, step="available_course")
elif request.form["step"] == "type_of_class":
session['course_name'] = str(form.course_name.data)
return render_template('manipulate-schedule.html', form=form, step="type_of_class")
elif request.form["step"] == "input_schedule":
session['type_of_class'] = form.type_of_class.data
return render_template('manipulate-schedule.html', form=form, step="input_schedule")
elif request.form["step"] == "input_teacher_email":
if form.validate_on_submit():
student_email = str(session.get('student_email'))
course_name = str(session.get('course_name'))
type_of_class = str(session.get('type_of_class'))
schedule_month = form.schedule_month.data
schedule_day = form.schedule_day.data
start_at = str(form.start_at.data)
end_at = str(form.end_at.data)
teacher_email = form.teacher_email.data
student = db.session.query(Student).filter_by(email=student_email).first()
course = db.session.query(Course).filter_by(name=course_name).first()
teacher = Teacher.query.filter_by(email=teacher_email).first()
# test the result
test_all_data = str(student_email) + str(course_name) + str(type_of_class) + str(schedule_month) + str(
schedule_day) + str(start_at) + str(end_at)
print('test', test_all_data)
schedule = Schedule(
student_id=student.id,
course_id=course.id,
type_of_class=type_of_class,
schedule_month=schedule_month,
schedule_day=schedule_day,
start_at=start_at,
end_at=end_at,
teacher_id=teacher.id
)
db.session.add(schedule)
try:
db.session.commit()
except Exception as e:
db.session.rollback()
return redirect(url_for('operator.all_schedules'))
return render_template('manipulate-schedule.html', form=form, step="input_teacher_email")
return render_template('manipulate-schedule.html', form=form)
When I try to insert the data directly without nested form, it works perfectly.
But whenever I try to use a nested form like above, the URL just redirects without inserted to the database. The thing that makes me confuse is, it just redirect without any error message.
So, the point of my question is, is it posible to insert data to the database if we using nested form..?

Generally, forms could not be nested - Can you nest html forms?
Specifically, did you look at the data that are being POSTed by the form?
To avoid nesting forms in this case, you can wrap all subforms in the one <form> tag without any need to have multiple form tags or even nesting them.

Related

how to search in mulit model using django

i want search from all my model in database , so i create this search functions for do this ... but always i got ' No results for this search '
how to fix this ?
view.py:
def search(request):
if request.method == 'GET':
query= request.GET.get('q')
submitbutton= request.GET.get('submit')
if query is not None:
home_database= Homepage.objects.filter(name__icontains=query,app_contect__icontains=query,page_url__icontains=query,app_image__icontains=query)
pcprograms_database= PCprogram.objects.filter(name__icontains=query,app_contect__icontains=query,page_url__icontains=query,app_image__icontains=query)
androidapk_database= AndroidApks.objects.filter(name__icontains=query,app_contect__icontains=query,page_url__icontains=query,app_image__icontains=query)
androidgames_database= AndroidGames.objects.filter(name__icontains=query,app_contect__icontains=query,page_url__icontains=query,app_image__icontains=query)
antiruvs_database= Antivirus.objects.filter(name__icontains=query,app_contect__icontains=query,page_url__icontains=query,app_image__icontains=query)
systems_database= OpratingSystems.objects.filter(name__icontains=query,app_contect__icontains=query,page_url__icontains=query,app_image__icontains=query)
pcgames_database= PCgames.objects.filter(name__icontains=query,app_contect__icontains=query,page_url__icontains=query,app_image__icontains=query)
results= list(chain(home_database,pcprograms_database,androidapk_database,androidgames_database,antiruvs_database,systems_database,pcgames_database))
context={'results': results,
'submitbutton': submitbutton}
return render(request, 'html_file/enterface.html', context)
else:
return render(request, 'html_file/enterface.html')
else:
return render(request, 'html_file/enterface.html')
html search form :
<form id="search_form" action="{% url 'search' %}" method="GET" value="{{request.GET.q}}">
<input id="search_box" type="text" name="q" value="{{request.GET.q}}"
placeholder=" Search For ... "/>
<input id="search_button" type="submit" name="submit" value="Search"/>
</form>
html file :
{% if submitbutton == 'Search' and request.GET.q != '' %}
{% if results %}
<h1> <small> Results for </small><b>{{ request.GET.q }}</b> : </h1>
<br/><br/>
{% for result in results %}
<label id="label_main_app"> <img id="img_main_app_first_screen" src="{{result.app_image.url}}" alt="no image found !" height="170" width="165" > {{result.name}} <br><br> <p id="p_size_first_page"> {{result.app_contect}} <br> <br> <big> See More & Download </big> </p>
</label>
{% endfor %}
{% else %}
<h3> No results for this search </h3>
{% endif %}
{% endif %}
any help please ?
If you are trying to filter with multiple model fields you need Q from django.db.models
Homepage.objects.filter(Q(name__icontains=query)&Q(app_contect__icontains=query),....

Select a specific object from a queryset django

Is there any way to select a specific object that is found in the results of a queryset like selecting an item in an array.
In arrays, you can select a specific item based on its position:
arrayName = {55, 33, 34, 23}
arrayName[2]
result = 34
I want to accomplish the same thing with queryset results
Users in database = {Steve, Chris, Jame, Cole, Casper, Courtney}
Query will filter the names that start with c
result = {Chris, COle, Casper, Courtney}
After I get the results, I want to select Casper from the results...
is there a way to do it like an array.
something like results[2]
UPDATE
So I have the part of the view working that will specify a specific record.
My only other question is to see if it is possible to do the same thing in the HTML tempalte file... Here is what I have in the view and html file. is there a way to do the same thing ht ehtml file...
view.py
i=0
for form in formset:
cd = form.cleaned_data
currentAmount = cd['amount']
currentDescription = cd['description']
print(currentAmount)
print(currentDescription)
currentTrans = transactions[i]
currentTrans.amount = currentAmount
currentTrans.description = currentDescription
currentTrans.save()
print(currentTrans)
i = i + 1
html
<form action="." method="POST">
{% csrf_token %}
{{ SplitFormSet.management_form }}
{% for form in SplitFormSet %}
{{ form.as_p }}
{% endfor %}
<p>Tax: <input type="text" name="tax" value=""></p>
<p>Tip: <input type="text" name="tip" value=""></p>
<input type="submit" name="submit" value="submit">
</form>
I tried this but it game me an error becuase 'i' is not a tag
<form action="." method="POST">
{% csrf_token %}
{{ SplitFormSet.management_form }}
{% i = 0 %}
{% for form in SplitFormSet %}
{{ transactions[i] }}
{{ form.as_p }}
{% i = i + 1 %}
{% endfor %}
<p>Tax: <input type="text" name="tax" value=""></p>
<p>Tip: <input type="text" name="tip" value=""></p>
<input type="submit" name="submit" value="submit">
</form>
names=Model.objects.filter(name__istartswith='c')
print(names[2])
In place of name you have put the field name of you model

Restrict each user to only vote once (Polls, django, python)

I found an similar question here, but unlike there and unlike in django official tutorial , I don't have a separate Choice class. How can I restrict every user to vote just one? What should I change in my code?
my models.py:
from django.contrib.auth.models import User
class Law(models.Model):
#some code here
yes_votes = models.IntegerField(default=0)
no_votes = models.IntegerField(default=0)
class Voter(models.Model):
user = models.ForeignKey(User)
law = models.ForeignKey(Law)
my views.py:
class LawDetailView(generic.DetailView):
model = Law
template_name = 'law_detail.html'
def get_queryset(self):
"""
Excludes any petitions that aren't published yet.
"""
return Law.objects.filter(pub_date__lte=timezone.now())
class LawResultsView(generic.DetailView):
model = Law
template_name = 'law_results.html'
def law_yes_vote(request, law_id):
if Voter.objects.filter(law_id=law_id, user_id=request.user.id).exists():
return render(request, 'law_detail.html', {
'law': p,
'error_message': "Sorry, but you have already voted."
})
else:
p = get_object_or_404(Law, pk=law_id)
p.yes_votes += 1
p.save()
return HttpResponseRedirect(reverse('laws:law_results', args=(p.id,)))
def law_no_vote(request, law_id):
if Voter.objects.filter(law_id=law_id, user_id=request.user.id).exists():
return render(request, 'law_detail.html', {
'law': p,
'error_message': "Sorry, but you have already voted."
})
else:
p = get_object_or_404(Law, pk=law_id)
p.no_votes += 1
p.save()
return HttpResponseRedirect(reverse('laws:law_results', args=(p.id,)))
my law_detail.html:
{% if request.user.is_authenticated %}
{% if error_message %}
<h1 >{{ error_message }}</h1>
{% else %}
<div class="row" id="row-voting">
<form action="{% url 'laws:law_yes_vote' law.id %}" method="post">
{% csrf_token %}
<button class="btn btn-success" name="choice" id="choice{{ forloop.counter }}" value="{{ choice.id }}" >
<label >YES</label>
</form>
<form action="{% url 'laws:law_no_vote' law.id %}" method="post">
{% csrf_token %}
<button class="btn btn-danger" name="choice" id="choice{{ forloop.counter }}" value="{{ choice.id }}" >
<label >NO</label>
</form>
</div>
{% endif %}
{% else %}
<h1>Please, register</h1>
{% endif %}
It looks like you have forgotten to create the voter instance after the user has voted.
def law_yes_vote(request, law_id):
if Voter.objects.filter(law_id=law_id, user_id=request.user.id).exists():
return render(request, 'law_detail.html', {
'law': p,
'error_message': "Sorry, but you have already voted."
})
else:
p = get_object_or_404(Law, pk=law_id)
p.yes_votes += 1
p.save()
Voter.objects.create(law_id=law_id, user_id=request.user.id)
return HttpResponseRedirect(reverse('laws:law_results', args=(p.id,)))
You'll need to update law_no_vote in the same way.

Error while submitting form in Django. ValueError: invalid literal for int() with base 10: ''

I can't get the following problem solved even with the answers to related questions on this site.
At the moment I am doing the Django tutorial but got stuck with the form.
The following error, that i get whem submitting a favorite song, is bugging me:
ValueError: invalid literal for int() with base 10: ''
I tried everything i could think of (e.g. selected_song = album.song_set.get(pk= int(request.POST['song'])) and googled looking for an answer but i can't seem to fix it. I appreciate any help.
detail.html
<form action="{% url 'music:favorite' album.id %}" method = "post">
{% csrf_token %}
{% for song in album.song_set.all %}
<input type = "radio" id = "song{{ forloop.counter }}" name = "song" value = "{{ song_id }}" />
<label for="song{{ forloop.counter }}">
{{ song.song_title }}
{% if song.is_favorite %}
<img src="http://http://i.imgur.com/b9b13Rd.png" />
{% endif %}
</label><br>
{% endfor %}
<input type="submit" value="Favorite">
</form>
views.py
def favorite(request, album_id):
album = get_object_or_404(Album, pk = album_id)
try:
selected_song = album.song_set.get(pk= int(request.POST['song']))
except (KeyError, Song.DoesNotExist):
return render(request, 'music/detail.html', {
'album':album,
'error_message': "You didn't select a valid song"
})
else:
selected_song.is_favorite = True
selected_song.save()
return render(request, 'music/detail.html', {'album': album})
In your template you are doing
<input type = "radio" id = "song{{ forloop.counter }}" name = "song" value = "{{ song_id }}" />
{{song_id}} is None in this case. You need to use {{song.id}}.
<input type = "radio" id = "song{{ forloop.counter }}" name = "song" value = "{{ song.id }}" />
So a blank string '' is passed to your view, which you are trying to pass to int hence the error.

Python Django, submit multiple forms

i am fairly new to Django and Python and have the following problem:
I have a quiz with multiple answers.
Every answer has a form attached to it, which posts data to a view that creates an objects from a Model.
But i cant post all forms, because its only posting the 5th one.
views.py:
def quiz(request, quiz_id=1):
cs = {}
cs.update(csrf(request))
height=75*Frage.objects.count()
height_menu = height + 10
if Frage.objects.count() == 0:
height = 170
height_menu = height
len_quiz = len(Quiz.objects.get(id=quiz_id).title)
count=Frage.objects.filter(quiz=quiz_id).count
count_aw = 0
aw = Frage.objects.filter(quiz=quiz_id)
cs.update({'quiz': Quiz.objects.get(id=quiz_id),
'Frage': Frage.objects.filter(quiz=quiz_id),
'len': len_quiz,
'hg': height,
'hg_m': height_menu,
'user': request.user,
'aw': Antwort.objects.all(),
'count': count,
'count_aw': count_aw})
return render_to_response('quiz.html', cs)
def check_view(request):
check = request.POST.get('aw_check', '')
user_id = request.POST.get('user_log', '')
user_act = User.objects.get(id=user_id)
frage_id = request.POST.get('frage', '')
frage = Frage.objects.get(id=frage_id)
antwort_id = request.POST.get('antwort', '')
antwort = Antwort.objects.get(id=antwort_id)
richtig = request.POST.get('richtig', '')
quiz_id = request.POST.get('quiz', '')
quiz = Quiz.objects.get(id=quiz_id)
res = Results(quiz=quiz, frage=frage, user=user_act, richtig=richtig, choice=check, aw=antwort)
res.save()
return HttpResponseRedirect('/quiz/all/')
template:
{% if Frage.count == 0 %}
<br>
<h1 id="main_link" style="text-align: center" align="center">Keine Fragen vorhanden!</h1>
{% endif %}
<ol>
{% for Frage in Frage %}
<li><div id="frage">{{Frage.content}}</div></li>
{% for aw in Frage.antworten.all %}
<form action="/quiz/check/" name="{{ aw.content }}" method="post">{% csrf_token %}
<label for="aw_check">{{ aw.content }}</label>
<input type="checkbox" name="aw_check" id="aw_check">
<input type="hidden" name="user_log" value="{{ user.id }}">
<input type="hidden" name="frage" value="{{ Frage.id }}">
<input type="hidden" name="antwort" value="{{ aw.id }}">
<input type="hidden" name="quiz" value="{{ quiz.id }}">
{% if aw.richtig %}
<input type="hidden" name="richtig" value=True>
{% else %}
<input type="hidden" name="richtig" value=False>
{% endif %}
<input type="submit" value="Abgeben" />
<br>
</form>
{% endfor %}
{% endfor %}
</ol>
<script language="javascript">
function call_submitforms(){
{% for Frage in Frage %}
{% for aw in Frage.antworten.all %}
setTimeout("document.{{ aw.content }}.submit()",1000);
{{ check.it }}
{% endfor %}
{% endfor %}
}
</script>
<input type="button" value="Abschicken" onclick="call_submitforms()" />
I think you should redesign your program. My understanding is that form submission can only handle one form. Here are some work-arounds using Django/Python. But, for your case, if you're designing a quiz, all of the answers should be part of a single form. Instead of returning {% for Frage in Frage %} I would do something like this (you'll have to redesign your models and views first):
//one form contains all questions
form action="/quiz/check/" name="{{ aw.content }}" method="post">{% csrf_token %}
//list the questions as part of that form
{%for Frage in quiz.Frages%}
<input type="hidden" name="user_log" value="{{ user.id }}">
<input type="hidden" name="antwort" value="{{ aw.id }}">
<input type="hidden" name="quiz" value="{{ frage.id }}">
{% endfor %}
//submit all of the data for each page of the quiz in one form
<input type="hidden" name="richtig" value=True>
{% else %}
<input type="hidden" name="richtig" value=False>
{% endif %}
<input type="submit" value="Abgeben" />

Categories