I am trying to use a Django form to populate a Python object (not a Django model).
I have the feeling I can only either:
build a simple form and populate manually
use a Django model as proxy
The extra difficulty is the form send a GET request
The class
class Search:
def __init__(self):
self.min_area = 0
self.max_area = 999
The form
from django import forms
class MainSearchForm(forms.Form):
min_area = forms.IntegerField(label="Minimum", required=False)
max_area = forms.IntegerField(label="Maximum", required=False)
The view
from django.http import HttpResponse
from django.template import loader
from front.forms.search.main import MainSearchForm
from front.gears.search import Search
def main(request):
search = Search()
form = MainSearchForm(request.GET, {})
# manual populating i want to avoid
if form.has_changed() and form.is_valid():
search.min_area = form.cleaned_data['min_area']
search.max_area = form.cleaned_data['max_area']
tpl = loader.get_template('front/search/main.html')
ctx = {
'form': form,
'search': search
}
return HttpResponse(tpl.render(ctx, request))
For now, I am populating manually in the view but I am quite sure there is a better way to do it.
Am I missing a part of the documentation ?
You can use setattr:
for key in form.cleaned_data:
setattr(search, key, form.cleaned_data[key])
Related
What does it mean when we write request.session["tasks"] and assign it to something in django views? Like in the script below in the index function request.session["tasks"] = [ ],does that mean an empty list named tasks has been created for that particular session? and if so, where exactly all these session details are stored in django? and also what does cleaned_data["task"] in the add function is exactly doing in this script? I tried looking in the documentation but couldn't find any satisfactory information about this, so I'm sorry if this sounds a little stupid but I'm new to django and sometimes the syntax really confuses me,Any help is appreciated!
from django.shortcuts import render
from django import forms
from django.http import HttpResponseRedirect
from django.urls import reverse
# Create your views here.
class NewTaskForm(forms.Form):
task = forms.CharField(label = "New Task",min_length=8,max_length=16)
priority = forms.IntegerField(label="Priority",min_value=1,max_value=5)
def index(request):
if "tasks" not in request.session:
request.session["tasks"] = []
return render(request,"index.html",
{
"tasks":request.session["tasks"]
})
def add(request):
if request.method == "POST":
vari = NewTaskForm(request.POST)
if vari.is_valid():
task = vari.cleaned_data["task"]
request.session["tasks"] += [task]
return HttpResponseRedirect(reverse("index"))
else:
return render(request,"other.html",
{
"form":vari
})
return render(request,"other.html",{
"form" : NewTaskForm()
})
Yes, It means an empty list named tasks has been created for that particular session. and django stores the session data in 'django_session' table.
cleaned_data is used for validating the data.
# This line is used to pass the validated data from the form input.
task = vari.cleaned_data["task"]
I have a view in django that sign's up a client and I have a model for the client and a form that looks like this:
from django.forms import ModelForm
from api.models.client import Client
class SignUpForm(ModelForm):
class Meta:
model = Client
fields = ['first_name', 'last_name']
In my view I would like to validate the data in the request but my problem is that the paramters in the request are camelCase and not snake_case so when I try to validate the data it doesn't work.
def sign_up(request):
body = json.loads(request.body)
form = SignUpForm(body)
print(form.is_valid())
return HttpResponse('this is a test response')
Is there a clean way of making this work? Also is this the correct way to do what I'm trying to do?
You can iterate through the body keys, use regex to rename the key and adding to a new dictionary.
def camel_to_snake(val):
return re.sub('([A-Z]+)', r'_\1', val).lower()
body = json.loads(request.body)
new_body = {camel_to_snake(k): v for k, v in body.items()}
here is based-class views code:
# views.py
class ObjectCreate(CreateView):
model = ObjectModel
fields = "__all__"
its simple to create an object and save it use this class.
I wonder how?
what if I want to use based-function views to achieve it?
Using a function view you would need to implement everything, including creating a form for your model:
def create_object(request):
if request.method == 'GET':
form = ObjectForm()
if request.method == 'POST':
form = ObjectForm(request.POST)
if form.is_valid():
instance = form.save() # instance created
# now redirect user or render a success template
return redirect(...)
# if request method is GET or form is invalid return the form
return render(request, 'path/template_name.html', {'form': form})
If you want to learn how the CreateView works, look at its source code. Or for easier overview of the structure, look at this site which lists all the Django CBVs.
You'll find that CreateView inherits from 9 other classes, has about 20 attributes (of which model and fields) and 24 methods that you can override to customise its behaviour.
I've got a basic django-haystack SearchForm working OK, but now I'm trying to create a custom search form that includes a couple of extra fields to filter on.
I've followed the Haystack documentation on creating custom forms and views, but when I try to view the form I can only get the error:
ValueError at /search/calibration/
The view assetregister.views.calibration_search didn't return an HttpResponse object. It returned None instead.
Shouldn't basing this on SearchForm take care of returning a HttpResponse object?
forms.py
from django import forms
from haystack.forms import SearchForm
class CalibrationSearch(SearchForm):
calibration_due_before = forms.DateField(required=False)
calibration_due_after = forms.DateField(required=False)
def search(self):
#First we need to store SearchQuerySet recieved after / from any other processing that's going on
sqs = super(CalibrationSearch, self).search()
if not self.is_valid():
return self.no_query_found()
#check to see if any date filters used, if so apply filter
if self.cleaned_data['calibration_due_before']:
sqs = sqs.filter(calibration_date_next__lte=self.cleaned_data['calibration_due_before'])
if self.cleaned_data['calibration_due_after']:
sqs = sqs.filter(calibration_date_next__gte=self.cleaned_data['calibration_due_after'])
return sqs
views.py
from .forms import CalibrationSearch
from haystack.generic_views import SearchView
from haystack.query import SearchQuerySet
def calibration_search(SearchView):
template_name = 'search/search.html'
form_class = CalibrationSearch
queryset = SearchQuerySet().filter(requires_calibration=True)
def get_queryset(self):
queryset = super(calibration_search, self).get_queryset()
return queryset
urls.py
from django.conf.urls import include, url
from . import views
urlpatterns = [
....
url(r'^search/calibration/', views.calibration_search, name='calibration_search'),
....
]
Haystack's SearchView is a class based view, you have to call .as_view() class method when adding a urls entry.
url(r'^search/calibration/', views.calibration_search.as_view(), name='calibration_search'),
This helped me.
"removing the "page" prefix on the search.html template did the trick, and was a good temporary solution. However, it became a problem when it was time to paginate the results. So after looking around, the solution was to use the "page_obj" prefix instead of "page" and everything works as expected. It seems the issue is that the haystack-tutorial assumes the page object is called "page", while certain versions of django its called "page_obj"? I'm sure there is a better answer - I'm just reporting my limited findings."
See this: Django-Haystack returns no results in search form
I am new to Django (1.5) and I am trying to do a basic POST form. I have a TemplateView that implements the form (passed to the template using get_context_data).
When the form fails for some reason (e.g. validation error), I want to show the form again, containing the data that the user has filled. When it succeeds, I want to redirect to a success page (e.g. the just-created item).
Here's what I've done so far:
class WriteForm(forms.Form):
subject = forms.CharField()
text = forms.CharField(widget=forms.Textarea)
# some other stuff
class WriteView(MailboxView):
# MailboxView extends TemplateView and defines some context
template_name = 'messages/write.html'
form_data = None
def post(self, request, *args, **kwargs):
# treat form data...
# lets make things simple and just assume the form fails
# I want to do something like that:
self.form_data = request.POST
# should I return something?
def get_context_data(self, **kwargs):
context = super(WriteView, self).get_context_data(**kwargs)
if self.form_data is None:
context['form'] = WriteForm()
else:
context['form'] = WriteForm(self.form_data)
return context
Thanks in advance!
Django already has a FormView that you might be able to use. If you want to see how it works, here's the code on GitHub.
If you want to write your own view instead of using the built in form view, you might also find it useful to look at the FormView in Django Vanilla Views, which has a simpler implementation.