Why Django raising ValueError? - django

This is my view.py file under my project folder.
When I add a value in ToDo list it raises this error?
The view my_day.views.index didn't return an HttpResponse object. It returned None instead.
views.py
from django.shortcuts import render, redirect
from .models import List
from .form import ListForm
from django.contrib import messages
# Create your views here.
def index(request):
if request.method == "POST":
form = ListForm(request.POST or None)
if form.is_valid():
form.save()
all_items = List.objects.all
messages.success(request, ('Task Added'))
return render(request, 'index.html', {'all_items': all_items})
else:
all_items = List.objects.all
return render(request, 'index.html', {'all_items': all_items})

In your view, you have 3 possible outcomes based on the if conditions but only 2 of them returns a HttpResonse object. More specifically, the if form.is_valid() only returns a HttpResponse object if this condition passes. If it doesn't, it will return None (basically nothing) because there is no else condition or other fallback.
You need to add an else condition to the if form.is_valid(). More so, you should implement another approach than to serve content on a POST request. As WillemVanOnsem have commented, check out the Post/Redirect/Get pattern. I have replaced the return render(...) instances where needed to achieve this, but will need some tweaking to work, for instance replace the view name (should be defined in your urls.py file).
def index(request):
if request.method == "POST":
form = ListForm(request.POST or None)
if form.is_valid():
form.save()
all_items = List.objects.all
messages.success(request, ('Task Added'))
# Replaced the render(...) with a redirect instead.
# Replace "index" with the name of the view (if not index)
return HttpResponseRedirect(reverse("index"))
else:
# Added fallback if the form.is_valid() didn't pass
messages.failure(request, ('Failed when saving task'))
return render(request, 'index.html', {'all_items': all_items})
else:
all_items = List.objects.all
return render(request, 'index.html', {'all_items': all_items})

Related

Django Form - setting data

I'm improving my English, be patient
My form is a ModelForm and all the necessary data is sent by the user, but I want dynamically set the field ["viagem"] with the last object in the queryset.
How to set a field after sending the data
def cadastro(request):
dono = Dono.objects.get(user=request.user)
if request.method == "POST":
form = VendaForm(dono, request.POST)
# Here I get the necessary data to call my qs
colocador_id = form["colocador"].value()
viagem = Colocador.objects.get(pk=colocador_id).viagem_set.last()
# I want something like this
form["viagem"] = viagem
if form.is_valid():
form.save()
else:
print('error')
print(form.errors)
else:
form = VendaForm(dono)
context = {"form": form, }
return render(request, 'dashboard/cadastro.html', context)
print(form.errors) => <ul class="errorlist"><li>viagem<ul class="errorlist"><li>This field is required</li></ul></li></ul>
Then you should not add this as a Form field. You thus exclude it from the fields in your ModelForm and work with:
from django.contrib.auth.decorators import login_required
from django.shortcuts import get_object_or_404
#login_required
def cadastro(request):
dono = get_object_or_404(Dono, user=request.user)
if request.method == 'POST':
form = VendaForm(dono, request.POST)
if form.is_valid():
form.instance.viagem = form.cleaned_data['colocador'].viagem_set.last()
form.save()
else:
print('error')
print(form.errors)
else:
form = VendaForm(dono)
context = {'form': form, }
return render(request, 'dashboard/cadastro.html', context)
Note: It is often better to use get_object_or_404(…) [Django-doc],
then to use .get(…) [Django-doc] directly. In case the object does not exists,
for example because the user altered the URL themselves, the get_object_or_404(…) will result in returning a HTTP 404 Not Found response, whereas using
.get(…) will result in a HTTP 500 Server Error.
Note: You can limit views to a view to authenticated users with the
#login_required decorator [Django-doc].

Can we use instance in the form?

hello guys i am working on form i didint find how to get instance in the form. This is not a model form
def form(request):
if request.method == 'POST':
form = Form(request.POST)
if form.is_valid():
else:
form = Form()
return render(request, 'app/form.html', {'form': form})
You should have a form class something like below:
forms.py
from django import forms
class NameForm(forms.Form):
your_name = forms.CharField(label='Your name', max_length=100)
Now To handle the form we need to instantiate it in the view for the URL where we want it to be published:
views.py
from django.http import HttpResponseRedirect
from django.shortcuts import render
from .forms import NameForm
def get_name(request):
if request.method == 'POST':
form = NameForm(request.POST)
if form.is_valid():
# process the data as required
# ...
# redirect to a new URL:
return HttpResponseRedirect('/thanks/')
else:
form = NameForm()
return render(request, 'name.html', {'form': form})
Refer the Django documentation for more details.
https://docs.djangoproject.com/en/3.0/topics/forms/

Django: didn't return a HttpResponse object error

I am trying to make a Post form, but HttPResponse occurs.In my code, there is a redirect method, and I think it is considered as a httpresponse, isn't it?
I am just a begineer, so if someone could find an easy mistake, I would appreciate
from django.shortcuts import render,redirect
from .forms import DayCreateForm
def index(request):
return render(request,'diary/day_list.html')
def add(request):
form = DayCreateForm(request.POST or None)
if request.method == 'POST'and form.is_valid():
form.save()
return redirect('diary:index')
context ={
'form':form
}
return render(request,'diary/day_form.html',context)
In your code there is no HttpResponse returned if request.method is not POST, so try to add a return of HttpResponse in the case of 'not Post'.
You are not returning any HTTP response if the requested method other than HTTP POST. So, try the below snippet
from django.http.response import HttpResponse
def add(request):
if request.method == 'POST':
form = DayCreateForm(request.POST or None)
if form.is_valid():
form.save()
return redirect('diary:index')
else:
return HttpResponse("form is not valid")
else:
form = DayCreateForm()
context = {
'form': form
}
return render(request, 'diary/day_form.html', context)

confirmation form step2.html Django

What is the best way to show confirmation on step2.html in Django?
forms.py:
from django import forms
class ContactForm(forms.Form):
name = forms.CharField()
email = forms.EmailField()
message = forms.CharField(widget=forms.Textarea())
views.py:
from django.views.generic import FormView
from .forms import ContactForm
from django.shortcuts import render, redirect
from django.http import HttpResponse
from django.http import HttpResponseRedirect
def step1(request):
if request.method == 'POST':
form = ContactForm(request.POST)
if form.is_valid():
#save and cleared_form
return HttpResponseRedirect('/step2/')
else:
form = ContactForm()
return render(request, 'step1.html', {'form': form})
def step2(request):
ctx = { 'Test_1': 'email#email.com'}
return render(request, 'step2.html', ctx)
step2.html:
{{Test_1}}
On step 2 I want to show fields submitted on step 1, how to achieve that?
Good solution will be to show step2.html in step1 view when valid form is submitted, instead of redirecting user to step2. That way you will have access to your form data in view and template.
When submitting confirmation, values from step 1 can be passed by hidden fields or saved into session storage.
Example:
def step1(request):
if request.method == 'POST':
form = ContactForm(request.POST)
if form.is_valid():
ctx = {'contact_data': form.cleaned_data}
return render(request, 'step2.html', ctx)
else:
form = ContactForm()
return render(request, 'step1.html', {'form': form})
You can save whole form data (cleaned_data) into session storage before redirection in step 1. That way you will be able to retrieve that data in step 2. Example:
def step1(request):
if request.method == 'POST':
form = ContactForm(request.POST)
if form.is_valid():
#save and cleared_form
request.session.contact_form = form.cleaned_data
return HttpResponseRedirect('/step2/')
else:
form = ContactForm()
return render(request, 'step1.html', {'form': form})
def step2(request):
contact_data = request.session.get('contact_form', None)
if contact_data is None:
return HttpResponseRedirect('/step1/')
# someone is entering step 2 directly, without submitted form in step 1, we should redirect him back to step 1.
ctx = {'contact_data': contact_data}
return render(request, 'step2.html', ctx)
Consider using Form wizard. It will handle for you passing submitted data between steps (using cookies or session). All you need to do is: create 2 views, one with proper form, one with just some confirmation button and in template for step 2 retrieve all data from step 1.

How to clear form fields after a submit in Django

I've this:
def profile(request, username):
if request.method == 'POST':
if request.user.is_authenticated():
new_message = Message(author = request.user)
form = MessagesForm(request.POST, instance = new_message)
else:
form = MessagesForm(request.POST)
if form.is_valid():
form.save()
else:
to_user = User.objects.get(username = username)
form = MessagesForm(initial = {'user': to_user.pk})
return render(request, "profile.html", {
'username': username,
'form': form,
'messages': messages,
})
This form submit a message and return the same page. My problem is that after the submit I see again my field filled with my information. How to clear it after the submit?
After saving form instead of showing post dict assign the empty form
form = EmployeeForm()
if request.method == "POST":
pDict = request.POST.copy()
form = EmployeeForm(pDict) #if not valid shows error with previous post values in corresponding field
if form.is_valid():
form.save()
form = EmployeeForm() # show empty form no need to give HttpResponseRedirect()
It's standard to redirect after form submission to prevent duplicates.
Just return a redirect to your form on success.
if form.is_valid():
form.save()
return http.HttpResponseRedirect('')
after save() you can return 'form' key with MessagesForm(request.GET) value.
return render(request, "profile.html", {
'username': username,
'form': MessagesForm(request.GET),
'messages': messages,
})
Usually you can initialize the same empty form after you have saved datas:
if request.method == "POST":
rf = RegistrationForm(request.POST)
if rf.is_valid():
print 'Saving datas..'
#logic to save datas
rf = PreRegistrationForm()
return render_to_response('registration/confirmation_required.html', {'settings': settings}, context_instance=RequestContext(request))
Try using HttpResponseRedirect('/') instead of HttpResponseRedirect('') in #Karthikkumar's answer, especially if your home view is an empty path, for instance you have in your urls.py file:
urlpatterns = [path('',views.home_view),]
I had similar issues as those discussed above where HttpResponseRedirect('') directed me to a blank page. Let me know if adding the slash works for you!
You can use this:
Sometimes you can use this idea take attrs={ "autocomplete":"off"} for each inputs.
You can redirect back to the initial post
post_url = request.build_absolute_uri(post.get_absolute_url())
return HttpResponseRedirect(post_url)
please note that 'post' is an instance of the model created
I am hoping you have already defined a logic for GET methods. In the case that you have, all you can do is simply add return request.META['HTTP_REFERER'] at the end.
See what I mean:
def profile(request, username):
if request.method == 'POST':
if request.user.is_authenticated():
new_message = Message(author = request.user)
form = MessagesForm(request.POST, instance = new_message)
else:
form = MessagesForm(request.POST)
if form.is_valid():
form.save()
else:
to_user = User.objects.get(username = username)
form = MessagesForm(initial = {'user': to_user.pk})
return HttpResponseRedirect(request.META['HTTP_REFERER'])
This should work, I just tested it.
**Maybe I am late but for Django 4.x developers can use: **
from .forms import TodoForm
from django.contrib import messages
from django.http import HttpResponseRedirect
def mytodos(request):
form = TodoForm()
if request.method =='POST':
form=TodoForm(request.POST)
if form.is_valid:
form.save()
messages.success(request,'Task saved successfully')
return HttpResponseRedirect('/todo/')
mycontext={'form':form}
return render(request, 'todo/todo.html',mycontext)
in my urls.py: , i have set path('todo/',views.mytodo, name='todolist')
As you can see, after saving form, mycode will redirect to /todo/ which is automatically refreshed after every submit and a fresh form comes again everytime. If you are a good django dev, you will understand what I did. Make sure to reply if you have any queries .Thanks :)
When we reload the page (F5 or ctrl+shift+R), it submits the previously sent data. so instead of refreshing, we will directly hit the url using return HttpResponseRedirect('/posts/')
This way it will show the page with empty form (now even if you refresh it will only show data, won't submit it previous data again)
from django.shortcuts import render, HttpResponseRedirect
from django.views import View
from .models import Post
from .forms import PostForm
class PostListView(View):
def post(self, request, *args, **kwargs):
posts = Post.objects.filter(author=request.user).order_by('-created_on')
form = PostForm(request.POST)
if form.is_valid():
new_post = form.save(commit=False)
new_post.author = request.user
new_post.save()
return HttpResponseRedirect('/posts/')
context = {
'post_list': posts,
'form': form
}
return render(request, 'social/post_list.html', context)