Datefield passing None to post data form a django form - django

I have a django form that has a datefield in it
class SearchForm(Form):
#otherifields
birth_date = forms.DateField(widget=DateInput(attrs={'classs':'datepicker form-control'}))
In my view i get the forms posted data
post_data = form.cleaned_data
and try to access the date with
date = post_data['birth_date']
but no matter if i set a date on my template or not the value is always None. I use this for the date widget throught all my Django project, and works fine in my ModelForms. But it won't say error of wrong date etc.
my django view
def search(request):
form = SearchForm(request.POST or None)
if request.method == 'POST'::
post_data = form.cleaned_data
customers = Customer.objects.filter(first_name__icontains=post_data['first_name'],
last_name__icontains=post_data['last_name'],
middle_name__icontains=post_data['middle_name'],
gender=post_data['gender'],
email__icontains=post_data['email'],
telephone__icontains=post_data['telephone'],
work_phone__icontains = post_data['work_phone'],
mobile__icontains=post_data['mobile'],
address__icontains = post_data['address'],
region__icontains = post_data['region'],
state__icontains = post_data['state'],
municipality__icontains = post_data['municipality'],
postal_code__icontains = post_data['postal_code'],
country__icontains = post_data['country'],
)
if post_data['birth_date']:
customers = customers.filter(birth_date=post_data['birth_date'])
#some other and returns
But if i print post_data['birth_date'] I always get None. What could be wrong? Am I missing something with forms?

Your code segment
if post_data['birth_date']:
customers.filter(birth_date=post_data['birth_date'])
is outside the scope of the search function. That could also be the reason it's value is None

Related

how to get field value from model

I have a model for registering with some fields.
All fields are models I fill in through the form like this.
def get_name(request):
if request.method == 'POST':
user_code = generate_code(8)
subject = 'code'
message = user_code
phone=request.POST['phone']
form = NameForm(request.POST)
if form.is_valid():
date_use = form.cleaned_data.get("date_visit")
time_use = form.cleaned_data.get("time_visit")
purpose_use = form.cleaned_data.get("purpose")
if Registration.objects.filter(date_visit=date_use,time_visit=time_use,purpose=purpose_use).count()==0:
Registration.objects.create(fio=request.POST['fio'],phone=request.POST['phone'],date_visit=request.POST['date_visit'],time_visit=request.POST['time_visit'],
number_car=request.POST['number_car'],purpose=request.POST['purpose'],
tso=request.POST['tso'])
request.session["phone"] = phone
request.session["code"] = user_code
return HttpResponseRedirect('endreg')
else:
form = NameForm()
return render(request, 'registers/detail.html', {'form': form})
The model also has a field
date_register = models.DateTimeField(verbose_name = 'date register', auto_now_add=True)
how can i write date_register value in request.session["date"] ?
Instead of using Registration.objects.create(...) you can use .save method:
obj = Registration()
obj.fio = form.cleaned_data["fio"]
...
obj.save()
request.session["date"] = str(obj.date_register)
By default django use JSONSerializer and it can't dump datetime objects.
The simplest solution is using PickleSerializer as SESSION_SERIALIZER, but it can cause performance issues (docs: https://docs.djangoproject.com/en/3.0/ref/settings/#std:setting-SESSION_SERIALIZER)
Another way to do it - write you custom json serializer, based on django serializer, but with default function for dumping datetime objects, or simple convert date to string format or timestamp before saving to session.

Django MultipleChoiceField restrictions on choices tuple

I am getting an error message when I try to use MultipleChoiceField with the CheckboxSelectMultiple widget. I built a form using Django's MultipleChoiceField that displays a set of checkboxes for the user to select:
class CheckBoxForm(forms.Form):
def __init__(self,*args,**kwargs):
arg_list = kwargs.pop('arg_list')
section_label = kwargs.pop('section_label')
super(CheckBoxForm,self).__init__(*args,**kwargs)
self.fields['box_ID'].choices=arg_list
print arg_list
self.fields['box_ID'].label=section_label
box_ID = forms.MultipleChoiceField(required=True, widget=forms.CheckboxSelectMultiple)
The view looks like this:
sat_list = (
('a','SAT1'),
('b','SAT2')
)
if request.method == 'POST':
form_scID = CheckBoxForm(request.POST,arg_list=sat_list,section_label="Please Select Satelites")
if form_scID.is_valid():
scID = form_scID.cleaned_data['box_ID']
return HttpResponse("Satellite: {sat}".format(sat=scID,type=taskType))
else:
form_scID = CheckBoxForm(arg_list=sat_list,section_label="Please Select Satelites")
return render(request, 'InterfaceApp/schedule_search.html', {'form3': form_scID})
When I try this I get the error: local variable 'scID' referenced before assignment, but it works when I set up the choices tuple using numbers as the first element, like this:
sat_list = (('1','SAT1'),('2','SAT2'))
Why do I have to set the first element as a number for it to work?
The forms don't have to be unique. You can specify a prefix for the form when you call it:
form_1 = DataTypeForm(request.POST or None,initial_value=True,prefix="1")
form_2 = DataTypeForm(request.POST or None,initial_value=False,prefix="2")

Add data to ModelForm object before saving

Say I have a form that looks like this:
forms.py
class CreateASomethingForm(ModelForm):
class Meta:
model = Something
fields = ['field2', 'field3', 'field4']
I want the form to have these three fields. However my Somethingclass also has field1. My question is - how do I add data to field1, if I am not using the ModelForm to collect the data. I tried doing something like this, but it isn't working and I am unsure on the proper way to solve this:
views.py
def create_something_view(request):
if (request.method == 'POST'):
# Create an object of the form based on POST data
obj = CreateASomething(request.POST)
# ** Add data into the blank field1 ** (Throwing an error)
obj['field1'] = request.user
# ... validate, save, then redirect
The error I receive is:
TypeError: 'CreateAClassForm' object does not support item assignment
In Django, what is the proper way to assign data to a ModelForm object before saving?
form = CreateASomething(request.POST)
if form.is_valid():
obj = form.save(commit=False)
obj.field1 = request.user
obj.save()
Sometimes, the field might be required which means you can't make it past form.is_valid(). In that case, you can pass a dict object containing all fields to the form.
if request.method == 'POST':
data = {
'fields1': request.user,
'fields2': additional_data,
}
form = CreateASomethingForm(data)
if form.is_valid():
form.commit(save)
There are two ways given by Django official
LINK : https://docs.djangoproject.com/en/3.0/topics/forms/modelforms/
Method 1]
author = Author(title='Mr')
form = PartialAuthorForm(request.POST, instance=author)
form.save()
Method 2]
form = PartialAuthorForm(request.POST)
author = form.save(commit=False)
author.title = 'Mr'
author.save()
Here is a more suitable way to add data especially used during testing:
First convert an existing entry into a dictionary with the model_to_dict function
from django.forms.models import model_to_dict
...
valid_data = model_to_dict(entry)
Then add the new data into this dictionary
valid_data['finish_time'] = '18:44'
This works better than setting the value in the form
update_form.finish_time = '18:44'
Create the form with the valid data and the instance
update_form = UserEntryForm(valid_data, instance=entry)
Do any assertions you require:
self.assertTrue(update_form.is_valid())
entry = update_form.save()
self.assertEqual(
entry.status,
1
)

Populate Django form from 3rd party POST with different field names

My Django app will be handling post data from a 3rd party payment processor. I would like to use a Django form to sanitize and deal with this data, but the POST variables have names that are not valid names for Django form fields. How can I re-map these to my form?
So, I have a form:
class PayResponseForm(forms.Form):
status = forms.Charfield()
message = forms.CharField()
avs_code = forms.CharField(max_length=1)
And the post I get from the 3rd part site looks like:
request.POST['FinalStatus']
request.POST['MErrMsg']
request.POST['avs-code']
How do I map these post variable to my form fields? Will it cause problems if, in my view, I just do something like request.POST['status'] = request.POST['FinalStatus']?
You can create your own dict for form init:
if request.method == 'POST':
if need_to_convert_post(request):
post = {
'field1': None,
'field2': None,
'field3': None,
}
post['field1'] = request.POST.get('SomeOtherField1', None)
else:
post = request.POST
form = Form1(post)
else:
form = Form1()
and detect when you need to change post:
def need_to_convert_post(request):
if 'uniqueCheckField' in request.POST:
return True
return False
For tidyness, you could use request.POST['status'] = request.POST.pop('FinalStatus'), otherwise it's perfectly fine to use your approach.

Django - Limit select field to queryset of foreign table?

I have two models as follows:
System_Contact
first_name
last_name
isOwner = CharField ('Y'/'N')
isMainContact = CharField ('Y'/'N')
System
mainContact = ForeignKey(System_Contact)
owner = ForeignKey(System_Contact)
billTo = ForeignKey(System_Contact)
So, when I show the System form in a web page, the user can select the mainContact owner and billTo contacts from a drop down menu to save to the System model. However, I want to filter the select fields in the System form so that they are like this:
mainContact Select box: -- only show System_Contacts that have isMainContact = 'Y'
owner Select Box: -- only show Syste_Contacts that have isOwner = 'Y'
As it is now, I know how to limit a select box by filtering the queryset, but I don't know how to filter the related Foreign Key querySet. Since the mainContact and owner fields are Foreign Keys, I need to filter the Foreign Table (System_Contact), not the table on which the form is built (System)
I know how to filter a normal, non Foreign Key type select box as follows:
form.fields["some_field"].queryset = Some_Model.objects.filter(some_field="Foo")
How would I 'extend' this so that it filters the Foreign table?
This is what I am trying currently, without success:
form.fields["mainContact"].queryset = System_Contact.objects.filter(isMainContact = 'Y')
Thanks
This is what I am trying currently, without success:
form.fields["mainContact"].queryset = System_Contact.objects.filter(isMainContact = 'Y')
Can you include your model form and view? That looks OK to me.
Another approach is to override the __init__ method of your model form and set the queryset there.
class SystemForm(ModelForm):
def __init__(self, *args, **kwargs):
super(SystemForm, self).__init__(*args, **kwargs)
self.fields["mainContact"].queryset = System_Contact.objects.filter(isMainContact = 'Y')
class Meta:
model = System
As an aside, I would recommend using a BooleanField instead of a CharField with 'Y' and 'N' as choices.
That syntax looks correct. Are you receiving an error or is it just not filtering and showing everybody? Try the System_Contact.objects.get(id=<some valid id>) to see if it gets only one or more. If it gets more, perhaps it is being populated from a different call than the one intended.
Well this is embarrassing...
As I was pasting in my view and model form as per Alasdair's request, I noticed my error. Here is my (incorrect) view:
def system_contacts(request, systemID):
sys = System.objects.get(pk=systemID)
if request.method == 'POST':
form = System_Contacts_Form(request.POST, instance=sys)
form.fields["systemOwner"].queryset = System_Contact.objects.filter(systemOwner__exact='Y')
form.fields["mainContact"].queryset = System_Contact.objects.filter(isMainContact__exact = 'Y')
if form.is_valid():
form.save()
return HttpResponseRedirect('/systems/')
else:
conts = Contact_List.objects.filter(systemID = sys.pk)
form = System_Contacts_Form(instance=sys)
return render_to_response('pages/systems/system_pages/contacts.html', {'sys':sys, 'form':form, 'conts':conts}, context_instance=RequestContext(request))
I had put the form.fields["systemOwner"]... part in the POST section of the view, not the GET section of the view.
Here is my corrected view:
def system_contacts(request, systemID):
sys = System.objects.get(pk=systemID)
if request.method == 'POST':
form = System_Contacts_Form(request.POST, instance=sys)
if form.is_valid():
form.save()
return HttpResponseRedirect('/systems/')
else:
conts = Contact_List.objects.filter(systemID = sys.pk)
form = System_Contacts_Form(instance=sys)
form.fields["systemOwner"].queryset = System_Contact.objects.filter(systemOwner__exact='Y')
form.fields["mainContact"].queryset = System_Contact.objects.filter(isMainContact__exact = 'Y')
return render_to_response('pages/systems/system_pages/contacts.html', {'sys':sys, 'form':form, 'conts':conts}, context_instance=RequestContext(request))
Now my corrected view works and the filtering works on the select inputs on the form. I would not have thought to look at that without your help.
Cheers :-)