Form fields not showing when including form template - django

The form fields don't show when including form in another template. This is the form:
class ClinicSearchForm(forms.Form):
q = forms.CharField()
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.fields['q'].label = 'Search for'
self.fields['q'].widget.attrs.update(
{'class': 'form-control'})
This is the template:
<form method="get">
{{ form.as_p }}
<input type="submit" class="btn btn-primary my-1" value="Search">
</form>
And the view:
def clinic_search(request):
form = ClinicSearchForm
results = []
if 'q' in request.GET:
form = ClinicSearchForm(request.GET)
if form.is_valid():
q = form.cleaned_data['q']
results = Clinic.objects.filter(name__icontains=q)
context = {
'form' : form,
'results' : results,
}
return render(request, 'guide/clinic/clinic_search.html', context)
I'm including the form with the include tag but I only get rendered the button, not the field.
The form shows when in its own url, but not when included in another template (this other template has no other forms).
What am I missing?

Related

how to add form as data in class-base views?

I used to send form as content in function-base-view and I could use for loop to simply write down fields and values like:
{% for x in field %}
<p>{{ x.label_tag }} : {{ x.value }} </p>
I don't remember whole the way so maybe I wrote it wrong but is there anyway to do this with class-based-views, because when I have many fields its really hard to write them 1by1
Not entirely sure if this is what you need. But still I will try to answer. I took an example with class AuthorDetail(FormMixin, DetailView) as a basis. In get_context_data saved the form itself. In the template, first I displayed the form, then the value from the bbs model and requested
form.message.label_tag. To get the tag, I looked at this documentation.
In the class, replace the Rubric model with your own. In the template path: bboard/templ.html replace bboard with the name of your application where your templates are located.
views.py
class Dw(FormMixin, DetailView):
model = Rubric
template_name = 'bboard/templ.html'
form_class = TestForm
context_object_name = 'bbs'
def get_context_data(self, **kwargs):
context = super(Dw, self).get_context_data(**kwargs)
context['form'] = self.get_form()
print(77777, context['form']['message'].label_tag())
return context
def post(self, request, *args, **kwargs):
self.object = self.get_object()
form = self.get_form()
if form.is_valid():
return self.form_valid(form)
else:
return self.form_invalid(form)
forms.py
class TestForm(forms.Form):
message = forms.CharField()
templates
<form method="post">
{% csrf_token %}
{{ form.as_p }}
<input type="submit" value="adding">
</form>
<h2>{{ bbs }}</h2>
<h2>{{ form.message.label_tag }}</h2>
urls.py
urlpatterns = [
path('<int:pk>/', Dw.as_view(), name='aaa'),
]

How to render a bound Django model form as HTML-safe?

I am trying to return a bound form that has been modified and has some arbitrary text and HTML inserted into it. I have done some research and have been able to successfully insert some arbitrary text into a bound form but I haven't found any way to render the injected HTML as HTML. It renders as plain text. How can I achieve my goal?
Here is the code:
# views.py
def multi_text(request):
if request.method == 'POST':
data = request.POST.copy()
form = MultilineForm(data=data)
if form.is_valid():
cd = form.cleaned_data
form.data['text'] = '<i>Hello hello</i>'
return render(request, 'multi_text.html', {'form': form})
else:
form = MultilineForm()
return render(request, 'multi_text.html', {'form': form})
# forms.py
class MultilineForm(ModelForm):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.fields['text'].widget.attrs.update({'class': 'form-control'}, verbose_name='Text', placeholder='Type your text here...')
self.data['text'] = '...'
class Meta:
model = Multiline
fields = ['text']
widgets = {
'text': Textarea(attrs={}),
}
# template.html
<form method="post" action="" class="form">
{% csrf_token %}
{{ form.text.as_widget }}
<span class="input-group-btn">
<input type="submit" value="Check" class="form-control btn btn-primary">
</span>
</form>

Django dropdown form submission invalid

Hey i am trying to use modelchoicefield to get a dropdown list in html. But the submission of form yields a invalid form. My code is given below.
views.py
class SubjectSelectFormView(View):
form_class = SubjectSelectForm
template_name = 'study/select_subject.html'
def get(self, request):
form = self.form_class(user=request.user)
return render(request, self.template_name, {'form':form})
def post(self, request):
form = self.form_class(request.POST)
if form.is_valid():
subject = models.Subject.objects.get(name=form['name'])
return HttpResponseRedirect('study:quiz', subject.subject_id)
else:
return HttpResponse('<h1>Failed</h1>')
forms.py
class SubjectSelectForm(forms.Form):
name = forms.ModelChoiceField(queryset=Subject.objects.all().order_by('name'), widget=forms.Select())
def __init__(self, *args, **kwargs):
user = kwargs.pop('user', None)
super(SubjectSelectForm,self).__init__(*args, **kwargs)
self.fields['name'].queryset = Subject.objects.filter(user_id=user)
html
{% extends 'basic_home_app/base.html' %}
{% block content %}
<br>
<form class="form-horizontal" action="" method="post" enctype="multipart/form-data">
{% csrf_token %}
{{ form.as_p }}
<input type="submit" value="Start">
</form>
{% endblock %}
First you should always render the same template with the bound form when a posted form is found to not be valid, this way you can display errors to the user:
def post(self, request):
form = ...
if form.is_valid():
...
else:
return render(request, self.template_name, {'form':form})
Inside your template, you can display errors using either:
{{ form.errors }} # all form errors
{{ form.non_field_errors }} # form errors that aren't for one specific field, use this if you're displaying the field errors separately
or
{{ form.name.errors }} # just the errors for one specific field
Second, I assume you want to initialise your form the same way when it's posted as when it's first displayed (empty) to the user via the get() request:
def post(self, request):
form = self.form_class(request.POST, user=request.user) # note the user
Otherwise your form.__init__() method will set as queryset only Subject objects where user_id is None.

Django form NEVER posts

This is rather weird. I've been using Django forms for a long time and can't figure this out.
I have a small form with 1 field for "Quantity". Whenever I submit the form nothing happens and it NEVER get's into my condition to check if the request method is a POST. I have put a pdb in the code as well and it never reaches. I am not sure why. Here is the code.
views.py
def show_product(request, product_slug, template_name='catalog/product.html'):
product_cache_key = request.path
product = cache.get(product_cache_key)
if not product:
product = get_object_or_404(Product, slug=product_slug)
cache.set(product_cache_key, product, settings.CACHE_TIMEOUT)
categories = product.categories.filter(is_active=True)
if request.method == 'POST':
import pdb; pdb.set_trace() # it NEVER hit's this
postdata = request.POST.copy()
form = ProductAddToCartForm(request, postdata)
if form.is_valid():
cart.add_to_cart(request)
if request.session.test_cookie_worked():
request.session.delete_test_cookie()
url = urlresolvers.reverse('show_cart')
return redirect(url)
else:
form = ProductAddToCartForm(request=request)
form.fields['product_slug'].widget.attrs['value'] = product_slug
request.session.set_test_cookie()
context = RequestContext(request, locals())
return render_to_response(template_name, context)
forms.py
class ProductAddToCartForm(forms.Form):
quantity = forms.IntegerField(widget=forms.TextInput(attrs={'class': 'input-quantity', 'placeholder': 'Qty'}), error_messages={'invalid': 'Please enter a valid quantity.'}, min_value=1)
product_slug = forms.CharField(widget=forms.HiddenInput())
def __init__(self, request=None, *args, **kwargs):
self.request = request
super(ProductAddToCartForm, self).__init__(*args, **kwargs)
def clean(self):
if self.request:
if not self.request.session.test_cookie_worked():
raise forms.ValidationError("Sorry, please enable your cookies.")
return self.cleaned_data
template
<form method="post" action=".">
{% csrf_token %}
{{ form.quantity.errors }}
{{ form.quantity }}
<input type="submit" name="submit" value="Add to Cart" class="btn btn-danger" />
{{ form.product_slug }}
</form>
When I click "Add to Cart" the URL goes from http://localhost:8000/product/arm-glove/ to this one http://localhost:8000/product/arm-glove/?csrfmiddlewaretoken=RFG0F1Lg0Eu3GcDhtYwPPCpy9Oct5zCX&quantity=2&submit=Add+to+Cart&product_slug=arm-glove
What am I missing here?
Turns out there was an unclosed tag used for the search which is a GET request so the form's POST was never being seen.

Django Template Form Render

My problem is not to show django form fields on template.It's silly but I just haven't found any solution.
class CommentForm(forms.ModelForm):
class Meta:
model = Comment
fields = ['name', 'email', 'text']
def __init__(self, content_type, id, *args, **kwargs):
super(CommentForm, self).__init__(*args, **kwargs)
self.content_type = content_type
self.id = id
def save(self, commit=True):
post_type = ContentType.objects.get_for_model(Post)
comment_type = ContentType.objects.get_for_model(Comment)
comment = super(CommentForm, self).save(commit=False)
if self.content_type == 'post':
comment.content_type = post_type
comment.post = self.id
else:
parent = Comment.objects.get(id=self.id)
comment.content_type = comment_type
comment.post = parent.post
comment.object_id = self.id
if commit:
comment.save()
return comment
my view:
def add_comment(request, content_type, id):
if request.method == 'POST':
data = request.POST.copy()
form = CommentForm(content_type, id, data)
if form.is_valid():
form.save()
return redirect(reverse('index'))
my add_comment template:
<form method="post" action="{% url 'add_comment' 'post' post.id %}">
{% csrf_token %}
{% if not user.is_authenticated %}
{{ form.name.label_tag }}
{{ form.name }}
{{ form.email.label_tag }}
{{ form.email }}
{% endif %}
{{ form.text.label_tag }}
{{ form.text }}<br>
<input type="submit" value="Comment" />
</form>
and I included like:
<button id="button" type="button">Add Comment</button>
<div id="post_comment_form">{% include 'articles/add_comment.html' %}</div>
</article> <!-- .post.hentry -->
why not django rendered form fields,despite of showing buttons?
EDIT:
I'm rendering form in post view.
def post(request, slug):
post = get_object_or_404(Post, slug=slug)
comments = Comment.objects.filter(post=post.id)
return render(request,
'articles/post.html',
{'post': post,
'form': CommentForm,
'comments': comments,
# 'child_comments': child_comments
}
)
You forgot to instantiate the form, change this line:
'form': CommentForm,
to this
'form': CommentForm(),
In your view, you're not sending any context variables to the template, so your 'form' object isn't available for your template to process.
For example, the following return statement will render your .html and pass along all local variables, this isn't necessarily the best option (how much do you want your template to have access to), but is simple:
from django.shortcuts import render
...
return render(request, "template.html", locals())
you can also pass a dictionary instead of all local variables. Here's the documentation for render