I've created objects in the admin page of my app, but I'm unable to call the object in my html template. I will put the views and the html lines below
from django.shortcuts import render, redirect
from .models import *
from .forms import *
def index(request):
tasks = Task.objects.all()
form = TaskForm()
if request.method == 'POST':
form = TaskForm(request.POST)
if form.is_valid():
form.save()
return redirect('/')
context = {'tasks': tasks, 'form': form}
return render(request, 'todo_app/list.html')
{% for task in tasks %}
<div class="task-container">
<p>{{task}}</p>
</div>
{% endfor %}
You forgot to send context to template:
Optional arguments
context
A dictionary of values to add to the template context. By default, this is an empty dictionary. If a value in the dictionary is callable, the view will call it just before rendering the template.
context = {'tasks': tasks, 'form': form}
return render(request, 'todo_app/list.html', context)
Related
In Django i am using bootstrap4 form from the package django-bootstrap4
it renderst the form using
{% bootstrap_form form %}
Now i just need only this part using a view like
#api_view(['GET'])
def rendertemplatetag(request)
form = DeviceForm()
rendered_template = bootstrap_form(form) <-- something like this
where renedered_template can be string
# return as json
return HttpResponse(rendered_template,status=200,content_type="application/json")
I am using DRF for this view
this view can be called with ajax and then the returned html can be substituded at its place
Django has a function render_to_string which you can use to render a template, and save the rendered HTML (well anything actually) as a string.
Solution
Have some template:
# some_template.html
{% bootstrap_form form %}
# views.py
from django.template.loader import render_to_string
#api_view(['GET'])
def rendertemplatetag(request)
form = DeviceForm()
rendered_template = render_to_string("some_template.html", {"form": form})
# return as json
data={"form":rendered_template}
return JSONResponse(data)
(django also has a JSONResponse object to automatically set all the correct headers for you etc.)
I'm trying to make a workflow where the user enters data on one page, then has to check the data and tick a tickbox to accept the T&C's. So the code has to check that the checkbox is checked before going on, but doesn't care until the second step.
It's not a bound field and I think that's the problem - I don't need a model just to handle a workflow, and I don't want to have to store, in a database, a simple ephemeral field in a form!
I'm running Django 2.1.5.
I've tried every possible combination of:
test_form.fields['tickbox'].value - doesn't exist, which is ridiculous
test_form.fields['tickbox'] == False - value doesn't change at all
request.POST['tickbox'] seems to go missing?
views.py
from django.http import HttpResponse
from django.template import loader
from django.forms import Form, CharField, BooleanField
class test_form(Form):
name = CharField()
tickbox = BooleanField(required=False, initial=False)
def testview(request):
if request.method == 'POST':
testform = test_form(request.POST)
if testform.fields['tickbox'] == True:
do_things()
else:
dont_do_things()
else:
testform = test_form()
template = loader.get_template('testform.html')
context = { 'testform : userform,
}
return HttpResponse(template.render(context, request))
I should be able to test the value of the field and get a changing response depending on if the user has ticked the box or not - I seem to get True regardless?
Here is a way how to solve your issue using Class Based Views and Function Based Views:
So, first:
forms.py:
from django import forms
class CheckboxForm(forms.Form):
name = forms.CharField()
tickbox = forms.BooleanField(required=False, initial=False)
def clean_tickbox(self):
'''Here we can check if the checkbox is checked or not'''
tickbox = self.cleaned_data.get('tickbox')
if not tickbox:
# Raise an error if the checkbox is not checked
raise forms.ValidationError("You must select this option")
# And return the value
return tickbox
With a class based view:
views.py:
from django.views import View
from django.contrib import messages
class CheckboxView(View):
template_name = 'checkbox.html'
form_class = forms.CheckboxForm
def get(self, request, *args, **kwargs):
form = self.form_class()
return render(request, self.template_name, {'form': form})
def post(self, request, *args, **kwargs):
form = self.form_class(request.POST)
# check if the form is valid
if form.is_valid():
# Use Django builtin messages framework
messages.success(request, "Checked!")
else:
messages.error(request, "not checked!")
return render(request, self.template_name, {'form': form})
With function based views:
from django.contrib import messages
def checkbox_func(request, *args, **kwargs):
template = 'checkbox.html'
if request.method == 'POST':
form = forms.CheckboxForm(request.POST)
# Check if the form is valid
if form.is_valid():
messages.success(request, "Checked!")
else:
messages.error(request, "Not checked!")
else:
form = forms.CheckboxForm()
return render(request, template, {'form': form})
urls.py:
from django.urls import path
from YOUR_APP import views
urlpatterns = [
# ... Your URLS
# Class Based Views
path('checkbox/', views.CheckboxView.as_view(), name="checkbox"),
# Function Based Views
path('checkbox2/', views.checkbox_func, name="checkbox_v2")
]
And your template: checkbox.html:
{% for message in messages %}
{{message}}
{% endfor %}
<form method="POST">
{% csrf_token %}
{{ form.as_p }}
<button type="submit">Submit</button>
</form>
Demo:
First of all, yes it is perfectly possible to have FormFields without them being declared in a Model.
You seem to be trying to do form validation on your own when django already handles simple cases like this for you. Let's start by looking at the documentation of BooleanField:
Validates that the value is True (e.g. the check box is checked) if
the field has required=True
Since that is exactly what you want to validate we can change the field definition:
tickbox = BooleanField(required=True, initial=False)
Since the documentation told us that django takes care of validating that the checkbox is actually checked there is no need for the custom validation code anymore. Let's look at the view next and refactor it:
def testview(request):
if request.method == 'POST':
testform = test_form(request.POST)
# check if the form is valid (that includes the checkbox being checked)
if testform.is_valid():
do_things()
else:
dont_do_things()
else:
testform = test_form()
template = loader.get_template('testform.html')
context = {'testform': userform} # added a closing single tick
return HttpResponse(template.render(context, request))
So instead of doing custom validation you just call the .is_valid() method of your Form instance to run validation. If you want to access any of the fields instead of using testform.fields[fieldname] you'd do testform.cleaned_data[fieldname] which only accesses fields that have been validated.
For more information on form processing in general I highly recommend reading through django's Working with forms.
I simply use the "cleaned_data" to check if the field is not part of the model but its just a form field.
so in your case this will be in your view
if testform.cleaned_data['tickbox'] == True:
do_things()
else:
dont_do_things()
I would like to use something similar to render_to_response function in Django but with HttpResponseRedirect.
Here's my views.py for render_to_response:
def somefunction(request):
return render_to_response('myTemplate.html',{'error': "error"})
mytemplate.html
{% if error %}
do something
{% endif %}
You could pass GET variables:
/mytemplate?variable1="variable_1"
You can also use the messages framework
from django.contrib import messages
def view(request):
# your code
messages.error(request, "ERROR")
HttpResponseRedirect("/mytemplate")
or maybe you can add a session
def view(request):
request.session['error'] = "ERROR"
return HttpResponseRedirect("/mytemplate")
def my_template(request):
if request.session.has_key('error'):
error = request.session.get('error')
del request.session['error']
return render(request, "myTemplate.html", locals())
In my django application the form never returns true even if I add the same data as in the admin application. My model.py looks like:
from django.db import models
from django.db.models import ImageField, signals
from django.dispatch import dispatcher
from django.forms import ModelForm
# Create your models here.
class Image(models.Model):
emailAddress = models.EmailField(max_length=75)
image = ImageField(upload_to='photos')
caption = models.CharField(max_length=100)
class UploadForm(ModelForm):
class Meta:
model = Image
My views.py looks like:
from django.http import HttpResponse, HttpResponseRedirect
from django.shortcuts import render_to_response
from competition.models import Image, UploadForm
# Create your views here.
def index(request):
images = Image.objects.all().order_by('emailAddress')
return render_to_response('images/index.html', {'images': images})
def uploadImage(request):
if request.method == 'POST': # If the form has been submitted...
form = UploadForm(request.POST) # A form bound to the POST data
if form.is_valid(): # All validation rules pass
emailAddress = form.cleaned_data['emailAddress']
image = form.cleaned_data['image']
caption = form.cleaned_data['caption']
i = Image(emailAddress=emailAddress, image = image, caption = caption)
i.save()
return HttpResponseRedirect('../image/')
else:
return render_to_response('images/upload.html', {'form': form})
else:
form = UploadForm() # An unbound form
return render_to_response('images/upload.html', {'form': form})
My template looks like:
<html>
<body>
<form enctype="multipart/form-data" action="/image/uploadImage" method="post">{% csrf_token %}
{{ form.as_p }}
<input type="submit" value="Submit" />
</form>
</body>
</html>
I can get it work correctly if I use the admin application but need a generic form and this does't work as it keeps asking for a either the email address or image (the error appears above the image field). So why might my form not be valid?
You need to instantiate your form with request.FILES as well as request.POST.
As an aside, you can save the model form instead of creating the Image by hand in the view.
You have a required image but you aren't binding the file data to the form.
form = UploadForm(request.POST)
should be
form = UploadForm(request.POST, request.FILES)
See https://docs.djangoproject.com/en/1.3/ref/forms/api/#binding-uploaded-files
FileField and ImageField fields have two places need to notice:
Require enctype="multipart/form-data" in form element.
<form enctype="multipart/form-data" method="post" action="/foo/">
Require request.FILES for form constructor.
form = UploadFileForm(request.POST, request.FILES)
Please refer:
https://docs.djangoproject.com/en/2.2/topics/http/file-uploads/
https://docs.djangoproject.com/en/2.2/ref/forms/api/#binding-uploaded-files
I'm having a problem with saving and updating a value to my database.
View:
def code_prof_edit(request, ampCode):
user_code = get_object_or_404(CodeUser, pk=ampCode)
if request.method =='POST':
form = CodeUserForm(request.POST, instance=user_code)
if form.is_valid():
form.save()
return HttpResponseRedirect('/codes/' + user_code.ampCode)
else:
form = CodeUserForm(instance=user_code)
return render_to_response('edit_code_user.html', {'user_code':user_code, 'form':form})
Relevant template form tag:
<form action="." method="POST"> {% csrf_token %}
{{form.as_p}}
<input type="submit" value="Save" />
</form>
Using the post method, the form correctly renders in the browser with all of the original values pre-populated, but if I change the values and click submit, none of the changes are made. Everything seems to work correctly in that the user is redirected to the correct page which means the save must have been called, but the info typed isn't being saved. Any and all help would be appreciated.
Edit entire view function:
from django.shortcuts import render_to_response, get_object_or_404
from django.http import *
from django.template import RequestContext
from codeuser.models import CodeUser
from codeuser.forms import CodeUserForm
import pdb
def code_prof_edit(request, ampCode):
user_code = get_object_or_404(CodeUser, pk=ampCode)
if request.method =='POST':
pdb.set_trace()
form = CodeUserForm(request.POST, instance=user_code)
if form.is_valid():
form.save()
return HttpResponseRedirect('/codes/' + user_code.ampCode)
else:
return render_to_response('home.html')
else:
form = CodeUserForm(instance=user_code)
return render_to_response('edit_code_user.html', {'user_code':user_code, 'form':form})
Edit: Figured it out. In the html form tag, the action attribute was incorrect. "." wasn't working, I needed "./edit" to get the correct result. Also, excluding that attribute all together worked perfectly too.