How to render a field when radio button is checked? - flask

I use WTForms and have a radio field like that:
class SimpleForm(Form):
radio_choice = RadioField('Label', choices=[('ip', 'IP'), ('ifname','Ifname')], default = 'ip')
In my html, I use jinja2 syntax:
{{ render_field(form.radio_choice) }}
{{ form.radio_choice.data }}
{% if form.radio_choice.data == ip %}
{{ render_field(form.weight) }}
{% else %}
{{ render_field(form.domain) }}
{% endif %}
How can I can get form.radio_choice.data on html, I wanna render domain field when form.radio_choice.data == ifname but I can only catch the value like that:
#app.route('/',methods=['post','get'])
def hello_world():
form = SimpleForm()
if form.validate_on_submit():
print form.radio_choice.data

It looks like you misunderstood what does jinja templating.
Jinja is interpreted on the server side, when you execute render_template()
After that, it's sent to the client and the client can fill up your form. So when your jinja template is interpreted, there is yet no data in your fields.
For your purpose, you will need to write some javascript code which executes on the client side, when the client is filling up the form. At this time, javascript can have the data and then display whatever you wish according to the choice on the radio button.
You can start by getting the radio button value : How to get the selected radio button’s value?

Related

Django Template strange behavior of layout

I have a function which generate a pdf.file and send it by email. And it works perfect. And I have a Table on my frontend
like above.
In my Django Model - Point 1 set by default as False, by condition if Point 1 is False - Cell 2 is empty, else - marked as Done. When I changing Table via Django form it works fine as well (frontend marked as Done). The problem is when I trying to change this via function which generate a pdf. I have added below lines of code in my pdf.generate Function:
def generatePdf(request, pk):
point = get_object_or_404(MyObj.objects.select_related('related'), pk=pk)
...
email.send(fail_silently=False)
point.one = True
print(point.one)
messages.success(request, 'Success')
return HttpResponseRedirect....
at the terminal I got the message that value changed properly from False to True
but for some reason Cell 2 in my Table on the frontend still is empty...
Part of frontend code:
{% for item in object_list %}
...
<td>
{% if item.one %}
<span><i class="fa fa-solid fa-check"></i></span>
{% else %}
<span></span>
{% endif %}
</td>
...
{% endfor %}
Summarizing the above said - why frontend condition working properly only if I change via Django form (function) and not if I trying to change via generatePdf function? Cell value in database changed properly in both ways!
I just forgot to add:
point.save()
in order to save to database changes.
So simple...

Django / an argument with HttpResponseRedirect is empty in my HTML page

In Views.py
return HttpResponseRedirect('add_scenes?submitted=True?linkToPrevScene=%s'%ScenePrevious)
ScenePrevious is a string containing "water2"
In my URL of add_scenes.html it works :
http://127.0.0.1:8000/scenes3d/add_scenes?submitted=True?linkToPrevScene=water2
But in the file add_scenes.html
{% if submitted %}
your scene was submitted successfully after {{ linkToPrevScene }}
{% else %}
this HTML code doesn't give output for {{ linkToPrevScene }} although {% if submitted %} is evaluated correctly
edit of my post:
This line also doesn't work if I replace the second ? by &
return HttpResponseRedirect('add_scenes?submitted=True&linkToPrevScene=%s'%ScenePrevious)
Sorry I couldn't comment but you need to pass the parameter linkToPrevScene through the view for you to receive it in the template.
**Note:**In Django You can not pass parameters with redirect. Your only bet is to pass them as a part of URL.
#...Rest of your view...
context['linkToPrevScene'] = Water2
redirect(reverse('add_scenes?submitted=True?linkToPrevScene=%s'%ScenePrevious, kwargs={ 'linkToPrevScene': Water2 }))
Use the links below for reference
Django documentaion:
Reverse
Redirect

How do I call my dict parameters from the view.py render in my template?

I have been working on this for two day, and have read almost every example on stackoverflow and consulted the django documentation. I am trying to pass my dict from the views.py to my template, but I keep getting the stupid "Could not parse the remainder" error. I'm not doing anything fancy. Just Href buttons passing in a parameter to represent what that button is. Then a template page opens using that parameter as a string to make the new page and url unique.
pass in with:
Call
urls.py
urlpatterns = [
url(r'^call=(\d+)/$', views.call, name='call')
]
views.py
def call(request, callID):
call_id = { 'id':callID }
return render(request, 'site/call.html', call_id)
Call template
{% extends 'site/layout.html' %}
{% block content %}
{% with call_id.get('id') as view_id %}
<h3 class="center-align blue lighten-3">Site # Room {{ view_id }}</h3>
Cancel
{% endwith %}
{% endblock %}
I have tried request.GET.get('id') and a bizillion other things. Can someone show me how I can actually parse those dict values I passed in?
You're not actually passing a dictionary at all. You're passing a single value, id, so you should just use that. And there is no need for any with block.
Site # Room {{ id }}

Wagtail not pulling through custom field panels

I'm overriding the wagtail AbstractFormField panel attribute in the following way:
...
before_input = RichTextField(verbose_name=_('before input'), blank=True)
after_input = RichTextField(verbose_name=_('after input'), blank=True)
panels = [
FieldPanel('label'),
FieldPanel('before_input'),
FieldPanel('after_input'),
FieldPanel('required'),
FieldPanel('field_type', classname="formbuilder-type"),
FieldPanel('choices', classname="formbuilder-choices"),
FieldPanel('default_value', classname="formbuilder-default"),
]
where the other panels are what comes out of the box.
This is working perfectly on the admin side and also saving as rich text into my database
I am pulling this through to my form in my template in the following way:
<form action="{% pageurl page %}" method="POST" class="lm-ls1" id="feedback-form">
{% csrf_token %}
{{ form.question1.help_text }} <!-- Simpler non interable way -->
{{ form.question1.before_input }}
<p>---------------</p>
{% for row in form.fields.values %}
{{row.choices}}
<p>---------------</p>
{{row.help_text}}
<p>---------------</p>
{{row.before_input}}
{% endfor %}
</form>
But I am only getting html output for the form panels excluding the before_input and after_input ones
I am getting through roughly the following:
Overall, how did you feel about the service you received today?
---------------
[('Very satisfied', 'Very satisfied'), ('Satisfied', 'Satisfied'),
('Neither satisfied nor dissatisfied', 'Neither satisfied nor dissatisfied'), ('Dissatisfied', 'Dissatisfied'), ('Very dissatisfied', 'Very dissatisfied')]
---------------
Overall, how did you feel about the service you received today?
---------------
---------------
How can I access the before_input field panel data stored in the _formfield wagtail table?
Bit late but hopefully this still helps you or someone else out there.
How Wagtail Forms Work
Wagtail forms provided to the view context for AbstractFormPage models is a fully instanced Django Form. This means that you will only ever find values in the form that can be given to a Django Form.
This includes fields, which are instances of Django's Fields (eg. CharField) and there is no simple way to add additional attributes to these fields.
You can see how the Form object is built in the Wagtail FormBuilder class definition.
1 - Make a Custom Template Tag
A somewhat simple way to get additional attributes on your FormField (Wagtail's FormField) is using a template tag.
Create a new file in in a folder templatetags in your app, and build a simple_tag that will take the form_page, the field (which will be a Django Field instance) and a string of the attribute name you want to get.
# myapp/templatetags/form_tags.py
from django import template
from django.utils.html import mark_safe
register = template.Library()
#register.simple_tag(name='form_field_attribute')
def form_field_attribute(form_page, field, attribute_name, default=None):
"""Return attribute on FormField where field matches 'field' provided."""
# field is a django Field instance
field_name = field.name
results = [
# if html is stored, need to use mark_safe - be careful though.
mark_safe(getattr(form_field, attribute_name, default))
# get_form_fields() is a built in function on AbstractFormPage
for form_field in form_page.get_form_fields()
# clean_name is property on AbstractFormField used for Django Field name
if form_field.clean_name == field_name]
if results:
return results[0]
return default
2 - Revise your form_page.html Template
In your template, cycle through your form (this is the Django Form instance) and use the template helper to get you the extra attributes you need. Example below, passing in page or self will work the same as they are both the instance of your FormPage.
<form action="{% pageurl page %}" method="POST" role="form">
{% csrf_token %}
{% for field in form %}
<div>{% form_field_attribute page field 'before_input' %}</div>
{{ field }}
<div>{% form_field_attribute page field 'after_input' %}</div>
{% endfor %}
<input type="submit">
</form>

Muliple instances of modelform

I have a list in my template. For each item in the list, I have a {{ modelform }} that contains a checkbox. I can check the box and it updates as should. The problem is that when I check the box for one item and submit, it submits for all of the checkboxes because they are the same in each instance. Is there a way to set up a unique checkbox instance for each item in the list?
Current each modelform checkbox renders the same like this:
<input name="is_solution" type="checkbox" class="is_solution" id="is_solution">
I also tried using
test = request.POST.get('checkbox')
and
test = request.POST.get('checkbox')
thinking that using this I might be able to post an update in my view. I think I am going about this all wrong and I am lost. Essentially, I would like to have a checkbox on a list much like here on stackexchange where you can confirm an answer. Any suggestions?
You have to use form's prefix in the view like (just something unique for each form object):
def foo(request, ...):
objs = Model.objects.filter(...)
forms = []
for i, obj in enumerate(objs):
form = ModelForm(instance=obj, prefix=str(i))
forms.append(form)
...
This will make sure each form has unique identifier, hence you will be able to submit a specific form.
And you can render the forms like usual in the template:
<form ...>
{% csrf_token %}
{% for form in forms %}
{{ form }}
{% endfor %}
</form>