Django class based views - return HTTPResponse - django

Why doesn't this work and it returns ValueError instead? I'm trying to get an input from the user and then, depending on the choice the user makes, render a specific view. If i move return redirect() back inside post function it does work.
class Choice(View):
form_class = SomeForm
template_name = 'app/object_form.html'
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)
if form.is_valid():
self.redirect_to_createform(request,form.cleaned_data['choice'])
else:
print('form not valid')
print(form.errors)
return render (request, self.template_name, {'form':form})
def redirect_to_createform(self, request, option):
print(option)
## Here i should have some logic to redirect to different views depending on the `option`
return redirect('to_somewhere')
Edit - I understand what the error means but how can i achieve the above mentioned goal.

You are missing return statement as below
if form.is_valid():
return self.redirect_to_createform(request,form.cleaned_data['choice'])

Related

Django, problem with render request: "The view main.views.licz didn't return an HttpResponse object. It returned None instead."

I'am trying to do a website and I have problem with uploading the file. On admin site I can upload and import any file but when I create view, I get this:
"The view main.views.licz didn't return an HttpResponse object. It returned None instead."
Here is the code from main.models:
class Plik(models.Model):
file = models.FileField(upload_to='uploads/')
Code from forms.py:
class upload(forms.Form):
title = forms.CharField(max_length=50)
file = forms.FileField()
And code from views.py:
def licz(request):
if request.method == "POST":
form = upload(request.POST, request.FILES)
if form.is_valid():
form.save()
return HttpResponseRedirect("main/licz.html", {"form":form})
else:
form = Plik()
return render(request, "main/licz.html", {"form":form})
Plz I am trying to solve this like 5 days...
def licz(request):
if request.method == "POST":
form = upload(request.POST, request.FILES)
if form.is_valid():
form.save()
return HttpResponseRedirect("main/licz.html", {"form":form})
else:
form = Plik()
return render(request, "main/licz.html", {"form":form})
# if request is GET, python will execute this part of the function
Your livz function does not return anything on a GET request.
If no return statement is given, Python will return None.
The return render(...) is only executed on a POST request (when the form is submitted) with invalid form.
You need to also render your page on other request method.
A typical form view should look like the following (pay attention to the indent):
def form_view(request):
if request.method == 'POST':
form = MyForm(data=request.POST)
if form.is_valid():
# do stuff with the form
return HttpResponseRedirect('/success-url')
else:
form = MyForm()
return render('my-template', {'form': form})
Pay attention to your conditions (if/else/...) and make sure your page return a response in every possible path the code execution takes.
def licz(request):
if request.method == "POST":
form = upload(request.POST, request.FILES)
if form.is_valid():
form.save()
return HttpResponseRedirect("main/licz.html")
else:
form = Plik()
return render(request, "main/licz.html", {"form":form})

Django framework python

I'm making a registration system for students in Django
When the user enters the student number, the system retrieves all the student data.
How can I work in this
def search(request):
if request.method== 'POST':
srch = request.POST['srh']
if srch:
match = Regiest_Form.objects.filter(Q(std_name__iexact=srch))
if match:
return render(request, 'Regiest_app/search.html', {'sr':match})
else:
messages.error(request,'no result')
else:
return HttpResponseRedirect('/search/')
else:
return render(request, 'Regiest_app/search.html')
Wow, you're missing a whole part of django's purpose.
Using django's form, you can delegate all your validation to your form.
If no results are found, your access errors using 'form.errors' and 'form.non_field_errors` within your template.
In forms.py
from django import forms
from .models import Regiest_Form
class RegisterSearchForm(forms.Form):
search=forms.Charfield(required=True)
def clean(self):
qs=Regiest_Form.objects.filter(Q(std_name__iexact=self.cleaned_data.get('search'))
if qs.exists():
self.add_error(field=None,error=forms.ValidationError("No results found"))
else:
return self.cleaned_data
#property
def results(self):
return Regiest_Form.objects.filter(Q(std_name__iexact=self.cleaned_data.get('search'))
In your views.py
from .forms import RegisterSearchForm
def search(request):
form = RegisterSearchForm(request.POST) if request.method== 'POST' else RegisterSearchForm()
if request.method== 'POST' and form.is_valid():
return render(request, 'Regiest_app/search.html',{'sr':forms.results, 'form':form})
return render(request, 'Regiest_app/search.html',{'form':form})

Ajax in function based view

I've come a cross a lot of tutorials regarding how to setup a class based view for ajax. Example:
class JoinFormView(FormView):
form_class = JoinForm
template_name = 'forms/ajax.html'
success_url = '/form-success/'
def form_valid(self, form):
response = super(JoinFormView, self).form_valid(form)
if self.request.is_ajax():
print(form.cleaned_data)
data = {
'message': "Successfully submitted form data."
}
return JsonResponse(data)
else:
return response
I'm wondering how would insert the required code for ajax into this function based view. Does the code required depend on whether or not I want to pull from or write to the db asynchronously?
def my_func_view(request):
template = 'accounts/profile.html'
form = Form123(request.POST or None)
if request.method == 'POST':
if form.is_valid():
instance = form.save(commit=True)
return redirect('/accounts/profile/')
else:
messages.error(request, 'There was an error.')
context = {'form': form,}
return render(request, template, context)
else:
context = {'form': form,}
return render(request, template, context)
Thanks for your help!
you do the same thing for the function based view too..
from django.http import JsonResponse
def my_func_view(request):
template = 'accounts/profile.html'
form = Form123(request.POST or None)
if request.is_ajax():
if form.is_valid():
instance = form.save(commit=True)
return JsonResponse({'status':'data'})
else:
messages.error(request, 'There was an error.')
return JsonResponse({'status':'data'})
else:
context = {'form': form,}
return render(request, template, context)

Why Django raising ValueError?

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})

Django: Redirect to Detail View after Creation

I'd like to redirect to a detail view after I successfully submitted a form and created the object.
My view.py
class ObjectCreateView(CreateView):
model = Object
form_class = ObjectCreateForm
template_name = 'frontend/base/object_create.html'
def get(self, request, *args, **kwargs):
form = ForecastConfigurationCreateForm()
form.fields['status'] = ModelChoiceField(queryset=ObjectStatus.get_object_status_list(self))
return render(request, self.template_name, {'form': form})
def post(self, request, *args, **kwargs):
form = self.form_class(request.POST)
if form.is_valid():
self.fcc_form = form.save(commit=True)
messages.add_message(self.request, messages.INFO, 'Good job!')
return render_to_response(reverse(viewname='object_detail', kwargs={'uuid': self.fcc_form.uuid}))
else:
messages.add_message(self.request, messages.ERROR, 'Error!')
return render(request, self.template_name, {'form': form})
The error message is:
TemplateDoesNotExist at /object_create/
/object_detail/3a3d6279-1531-45d4-9ba9-b691886facf4/
And the URL that's calling is:
http://test.com:8000/object_create/?next=/object_detail/a5b2a693-6f90-4b98-b9a2-fc2fe6a90995/
what I want it to be is
http://test.com:8000/object_detail/a5b2a693-6f90-4b98-b9a2-fc2fe6a90995/
Thanks!
Instead of trying to render the page, use HttpResponseRedirect instead:
class ObjectCreateView(CreateView):
...
def post(self, request, *args, **kwargs):
form = self.form_class(request.POST)
if form.is_valid():
self.fcc_form = form.save(commit=True)
messages.add_message(self.request, messages.INFO, 'Good job!')
return HttpResponseRedirect(reverse('object_detail', kwargs={'uuid': self.fcc_form.uuid}))
else:
messages.add_message(self.request, messages.ERROR, 'Error!')
return render(request, self.template_name, {'form': form})
just stumbled across the answer. The return should be:
return redirect(reverse('object_detail', kwargs={'uuid': self.fcc_form.uuid}))