I'm having trouble wiring my checkboxes together with the template to make a good user experience. I'm sending my form to the view which contains the following MyType which is described as:
models
class A(models.Model):
MyType = models.ManyToManyField(P)
forms
MyType = forms.ModelMultipleChoiceField(queryset=P.objects.all(), required=False, widget=forms.CheckboxSelectMultiple)
and the view is being sent as:
return render(request, "static/about.html", {'form': form})
and in the template, I have the following kind of structure
<li class="option table">
<div class="cell" id="center">
<div class="option-text">Option 1</div>
</div>
<div class="cell" id="right">
<div class="option-checkbox">
<div class="check"></div>
<input id="myid1" name="myname1" value="1" type="checkbox">
</div>
</div>
Now I can use answer: On a django form, how do I loop through individual options per field? to loop through, but this only gives the description. How do I recreate the actual HTML that deals with the options in the smartest way?
I've tried the shell to look at the objects, but I really don't see what I should be pulling in. i.e. in the template to recreate. What fields of each option should I pull in? or how do I get at the right info to build up my HTML such that the saving aspect of the form will work.
In a template I cannot do:
{% for field in form["MySmoking"] %}
{% endfor %}
so how could I modify the following:
{% for option in form.MyType.field.choices.queryset %}
{{ option.image }}
{{ option.title }}
{{ option.description }}
{% endfor %}
so, how would I spit out the HTML that builds the checkbox.
Thanks.
Related
I have a problem with trying to get a response from my HTML page using Django (admin).
I have a pretty simple div = contenteditable and need to pass data from this div back after the submit button was clicked.
Everything, including choosing selection and opening the intermediate page works fine. But when I tapped submit button, the condition if "apply" in request.POST failed to work.
Please, tell me, what I'm doing wrong?
This is my Django admin:
class QuestionAdmin(AnnotatesDisplayAdminMixin, admin.ModelAdmin):
def matched_skills(self, question):
return ', '.join(s.name for s in question.skills.all())
def update_skills(self, request, queryset):
if 'apply' in request.POST:
print("something")
skills = []
for question in queryset:
skills.append(self.matched_skills(question))
return render(request,
'admin/order_intermediate.html',
context={'skills': skills})
update_skills.short_description = "Update skills"
This is my order_intermediate.html page:
{% extends "admin/base_site.html" %}
{% block content %}
<form method="post">
{% csrf_token %}
<h1>Adjust skills. </h1>
{% for skill in skills %}
<div>
<div id="title" style="margin-left: 5px" contenteditable="true" > {{ skill }} </div>
</div>
{% endfor %}
<input type="hidden" name="action" value="update_status" />
<input type="submit" name="apply" value="Update skills"/>
</form>
{% endblock %}
Actually, request.POST is an HttpRequest object. For getting available keys in the body of the request, you need to use "request.POST.keys()" method. So, you can simply change your condition to:
if 'apply' in request.POST.keys():
print("something")
In my knowledge, you can not send div content with form submit. However you can use input tag with array in name attribute for this. This will send an array as post variable when submit
First, send skills as a enumerate object from your views
return render(request, 'admin/order_intermediate.html', context={'skills': enumerate(skills)})
Then edit your html to this (Note: if you have css in title id, change it to title class)
{% for i,skill in skills %}
<div>
<input class="title" name="skill[{{ i }}]" value="{{ skill }}" style="margin-left: 5px">
</div>
{% endfor %}
and handle array with any action you want to perform in update_skills()
for skill in request.POST.getlist('skill[]'):
# your code
Image of Form Fields Dissapeering When Not Selected
Hi all,
I am having trouble understanding why my fields are disappearing when they are not selected. I am rendering this form using Crispy Forms (followed via Youtube Tutorial). This feature was working earlier - however, I am not sure why it suddenly stopped working. I have a few other forms in this application and they are facing the same issue.
Here is the relevant code that is being used to generate the form
class BookAppointmentForm(forms.ModelForm):
class Meta:
model = BooksAppt
fields = '__all__'
labels = {
'hp_username': 'Doctor',
'appt_date': 'Appointment Date',
'p_username': 'Patients'
}
widgets = {
'appt_date': forms.TextInput(attrs={'type': 'date'})
}
def __init__(self, p_username=None, *args, **kwargs):
super(BookAppointmentForm, self).__init__(*args, **kwargs)
if p_username:
self.fields['p_username'].queryset = Patient.objects.filter(
p_username=p_username).values_list('p_username', flat=True)
Relevant HTML being used to render the form
<div class="container" style="background-color:#E6E6FA">
<div class="col-md-10 offset-md-1 mt-5">
<div class="card-body">
<h1 class="display-5 "> Booking an Appointment for {{ user }}</h1>
<p class="lead">Please Fill in the Following Form to Register an Appointment</p>
<hr class="my-4">
<form class="register" action="" method="post" autocomplete="off">
{% csrf_token %}
{{ form.errors }}
{{ form.non_field_errors }}
{{ form.p_username|as_crispy_field}}
{{ form.hp_username|as_crispy_field }}
{{ form.appt_date|as_crispy_field }}
<button type="submit" class="btn btn-success">Submit</button>
</form>
<br>
</div>
</div>
I feel as though the issue is something related to the bootstrap template I am using not playing nicely with crispy forms. I don't need a complete answer - just something to nudge me in the right direction. Please let me know if there is any other relevant information you need to help debug.
Thanks,
Shwinster
The issue was seen as a result of the bootstrap template. It was setting the text to white when not in focus. I was able to figure this out using inspect element and trying to see what stylistic properties were being set the form element.
I am having issues with having to hardcode the tags into the templates in Django. The reason I have issues is that I need to have the forms generated dynamically based on a framework I am working on.
That framework (written in Python) has a webinterface (hence Django) that requires forms for each module in the framework, depending on the data that needs to be submitted to that module.
So I am trying to get the form information (which fields, type of fields, labels etc.) from the module, which I currently am trying like so:
#framework/module.py
def form():
forms = '"upload": {"filename": "file","directory": "text"}'
return forms
The reason it is constructed like that, at this moment, is because I try to pass this information to the forms.py from Django so it can then be translated into what Django needs to create the output for the template.
Now I have tried a couple of ways on how to get it onto the template. The only problem is, that I have to create the form tags hardcoded into the template. I am trying to figure out how to get the form tags also generated dynamically based on the information supplied by the module. Because there could be modules that require multiple forms on the same page.
So in short, I am trying to do this:
{% for f in forms %}
{{f}}
{% endfor %}
Instead of this:
<form name="upload" action="foo" method="POST">
{{form}}
</form>
Is this possible in Django?
You can render your form fields manually in django, here is how.
{% for field in form %}
<div class="fieldWrapper">
{{ field.errors }}
{{ field.label_tag }} {{ field }}
{% if field.help_text %}
<p class="help">{{ field.help_text|safe }}</p>
{% endif %}
</div>
{% endfor %}
EDIT: I didn't get the question properly
You could have your form tag attributes in a dictionary and iterate through your forms in a structure like this:
Python:
forms = {
form_object: {"name": "upload", "action": "foo", "method": "POST"}
}
Template:
{% for form, tag_attributes in forms.items %}
<form name="{{tag_attributes.name}}" action="{{tag_attributes.action}}" action="{{tag_attributes.method}}">
Do stuff with your {{form}}
</form>
{% endfor %}
I downloaded and installed django-registration app. I also downloaded a template that has this strange piece of code
{{ form }}
that magically creates 4 labels and 4 textboxes for the user to enter his registration information. How does it work?
{% extends "registration/registration_base.html" %}
{% block title %}Register for an account{% endblock %}
{% block content %}
<table>
<form method='post' action=''>{% csrf_token %}
{{ form }}
<tr><td></td><td><input type="submit" value="Send activation email" /></td>
</form>
</table>
{% endblock %}
It is part of django forms. See the documentation for more info.
https://docs.djangoproject.com/en/1.3/topics/forms/
If you are really interested check out the source code.
https://code.djangoproject.com/browser/django/trunk/django/forms
A django form (but other objects, too) has a unicode method, which is invoked, when a string representation of the object is requested. As you can see in the code, it just passes the call on to as_table - which in turn uses a generic helper function: _html_output. This basically loops over all the fields and constructs the HTML which then is returned and displayed on the page.
I plan on creating a sidebar with changing elements (depending on the current url and authentication-status).
For example: The default sidebar shows a login and a tag cloud.
If a user is already logged in, I want to display a user menu.
If the current url is /tagcloud, I want to hide it from the sidebar.
Actually, I need a way which enables me to do something like this in a view:
def some_view(request):
if request.user.is_authenticated():
sidebar.remove('login')
sidebar.add('user_menu')
def tag_cloud(request):
sidebar.remove('tag_cloud')
Afterwards, I want to pass the sidebar (implicitly, without passing it to render_to_response) to the template where I have in mind to do something like this:
<div id="sidebar">
{{ sidebar }}
</div>
Is this possible?
You'd better do this in a context_processors.py file
That also mean you have to use a RequestContext when returning your views
def include_tagcloud(request):
if request.path == '/tagcould/':
tagcloud = Tags.objects.filter(active=True) #whatever
return {'tagcloud': tagcloud}
def include_login(request):
if request.user.is_authenticated():
loginform = MyLoginForm(request.POST)
#passing a Django form + POST data in the case of re-submit
return {'loginform' : loginform}
And then in your template :
{% if loginform %}
<form action="accounts/login/">
{{form.as_p}}
<input type="submit" name="Login">
</form>
{% endif %}
{% if tagcloud %}
{%for tag in tagcloud %}.....{%for}
{% endif %}
In this example the login form points to a fixed view,
if you want to catch the login form post on everyview, I don't know how to do
EDIT : if you don't use the CSRF features of Django, you could simply insert the login form in the base template without using any django form and pointing to a login view :
{% if user.is_authenticated %}
<form action="accounts/login/">
<input type="text" name="username"><input type="password" name="password">
<input type="submit" name="Login">
</form>
{% endif %}
Yeah, but you can use inheritance of templates as well as composition. Then include your sidebar in a parent template that is used/inherited from in all of your templates. Then it is easy to find the template for the sidebar: it's in a separate file.
Answer of #Dominique is correct but When you write something in context_processors that's load at any page of the website. That maybe makes a performance issue.
I think the right way to handle dynamic sidebar is simpletag and use where you need.
def get_sidebar():
tags = Tags.objects.filter(active=True)
latest_posts = Post.objects.all().order_by('-create_at')[:10]
html = render_to_string("sidebar.html", {
"tags": tags,
"latest_posts": latest_posts
})
return html
And now just use in template files:
<div class="col-md-4 sidebar">
{% get_sidebar %}
</div>
Also, you can pass request to simpletag to use user.is_authenticated for authenticated user access.