I'm still on this view. Now I have a ValidationError while trying to save the model instance. The error is:
Enter a valid date in YYYY-MM-DD format
The DateField is correctly filled, the type of instance passed to model is unicode. I have to do something like a cast from unicode to datetime or there's something I'm doing wrong before...?
This is the traceback.
Any idea?
Thanx
If you already know that the form is valid through form.is_valid(), consider working with cleaned_data instead of working directly with the request.POST:
if form.is_valid():
...
fattura.data = form.cleaned_data["data"]
fattura.diate = Decimal(form.cleaned_data["diate"])
...
Related
I yesterday asked this question without success but I have still been working on the problem. Save user input which is a string as object in db
. In short the question yesterday described how I wanted to have a registration key in my registration form to be able to restrict who can register themselves.
What I have done now is in the forms.py file have I created a key field as a ModelChoiceField with a textinput as the widget. When I write a key which exists in the DB I get the following error: "Select a valid choice. That choice is not one of the available choices.". I can't use Select as the widget as that would display the keys for the users.
I tried both methods in this post but without any success.
So the question know is, how can I have a TextInput with a ModelChoiceField?
Get the string from the user through a form with a CharField. Assuming you are using the CBV FormView, do the work in the form_valid method. Something like:
def form_valid( self, form):
key = form.cleaned_data['key']
try:
keyobj = Keything.objects.get( key=key)
# it's valid. do whatever.
return super().form_valid( form)
except Keything.DoesNotExist:
form.add_error( 'key', 'This is not a valid key')
return super().form_invalid( form)
Alternatively you could have a Validator on the form's key field which raises ValidationError if the Keything object does not exist.
I have the following equation in a Django 2.1 class:
import datetime
class FormBacktest(forms.Form):
dateStart= forms.DateTimeField(label="Date Start", widget=DateTimePickerInput()
dateEnd= forms.DateTimeField(label="Date End", widget=DateTimePickerInput()
timeInMin = int((dateEnd-dateStart).total_seconds()/60)
I know from the documentation that the DateTimeField is a datetime.datetime instance, so this question should be overcomed.
Any recommendations?
Well, DateTimeField is a form field, not a datetime instance. However when you take input from that field, you will get a datetime object. you can access its value from cleaned_data, for example like this:
# in view
def someview(request):
form = FormBacktest(request.POST or None)
if request.method == "POST": # its a post request
if form.is_valid():
date_start = form.cleaned_data.get('dateStart')
date_end = form.cleaned_data.get('dateEnd')
difference= date_end - date_start # time delta object
Please check the documentation on more details on how to get data from form. Also, please remove timeInMin from form.
I'm a bit confused about what you're trying to accomplish but I'll try to help.It seems like you're mixing up forms and model instances.
If you want to show timeInMin on the form then you'll need to make it an Integer field (probably small will do) and then use javascript to do the math and update the field when a user enters the start and end date.
IF you want to set timeInMin on submit in the database for the model instance, and you don't care about updating the value with Javascript on the form when it's updated, then you'll just do it in your form handler view, or even by overriding the model's save method.
With what you have now, the DateEnd isn't instantiated when you're trying to reference it, and DateEnd isn't a value anyway, it's a form field.
I have few questions regarding the Date and time fields both in the model and in the form class.
1.)In the docs for the date field what does the line "Normalizes to: A Python datetime.date object." mean? Does it mean that the field data stored in the request.POST dictionary on the submission of the form is a datetime.date object?If yes, then when does it do it when the form is submitted or do we have to call one of its functions?
2.)If i have a models.DateField() then while assigning data to it manually in a view should i assign a datetime.date object or a unicode object with the 'yyyy-mm-dd' format?
3.)If i take a date in my forms.DateField() in the '%d/%m/%y' format how do i assign it to my models.DateField() because that seems to accept only the 'YYYY-mm-dd' format?
If somebody could also suggest some links which explain these fields in detail with examples apart from the docs it would be helpful.
For first question, datefield saves date object and if you are saving any data( for example a string: "01-01-2015") to datefield, then you have to convert that data into date object. You will not get a date object in request.POST, if you use a form, then you can get it by using cleaned_data.(example below) From request.POST ,you will get an unicode object.( then you will need to convert it to date object, example below)
For second question, obviously you have to save dateobject, not unicode object.
For third question, in forms, To display initial field value properly formatted, use DateInput widget. To customize validation, use input_formats keyword argument of DateField. Here, from forms, you will get a date object in views, so it can be saved directly, like:
In model.py:
class DateModelClass(models.Model):
date= models.DateField()
In forms.py:
date= forms.DateField(widget=forms.DateInput(format = '%d/%m/%Y'), input_formats=('%d/%m/%Y',))
In views.py:
date_data= DateModelClass(date= form.cleaned_data['date'])
date_data.save()
Also you can convert a string of your desired format to Date Object like this:
>>import datetime
>>datetime.datetime.strptime(u"09/07/2014", '%d/%m/%Y').date()
I thought it would be easier to start using models form instead of regular forms(giving up on all the easy things modelform provides).
But when I try to do this:
>>> m = Model.objects.get(pk=1)
>>> f = ModelForm(instance=m)
>>> f.is_valid()
False
>>> f.save()
AttributeError: 'ModelForm' objects has no attribute 'cleaned_data'
I think django documentation is wrong by saying:
Every form produced by ModelForm also has a save() method. This
method creates and saves a database object from the data bound to
the form. A subclass of ModelForm can accept an existing model
instance as the keyword argument instance; if this is supplied, save()
will update that instance. If it’s not supplied, save() will create a
new instance of the specified model
Cause this is just not working for me.
Am I right that the django documentation is wrong?
Thanks in advance.
You may have forgotten to add "data" into the ModelForm instantiation according to the user's request.POST data.
f = ModelForm(data=request.POST, instance=m)
f.is_valid() # is True if the data is ok.
In any case, it would be better to post your relevant code: The model class, the model form class and your view.
EDIT: you must add a data= parameter (or the first parameter, if you don't name it) to a ModelForm initialization, if you want is_valid() to work. is_valid is here to check the given data against the various validation rules, and only if it's ok, lets you save the ModelForm. Initializing a ModelForm just with the instance= named parameter does not trigger any validation, because there is nothing new to validate.
I have a simple Django Form:
class testForm(forms.Form):
list = forms.CharField()
def getItems(self):
#How do I do this? Access the data stored in list.
return self.list.split(",") #This doesn't work
The list form field stores a csv data value. From an external instance of testForm in a view, I want to be able to look at the .csv value list stored in the form field.
Like others have already mentioned, you need to make use of the form's cleaned_data dictionary attribute and the is_valid method. So you can do something like this:
def getItems(self):
if not self.is_valid():
return [] # assuming you want to return an empty list here
return self.cleaned_data['list'].split(',')
The reason your method does not work is that the form fields are not your typical instance variables. Hope this helps!
What you usually do in django in a view to get the form data would be something like this.
form = testForm(request.POST)
if form.is_valid:
# form will now have the data in form.cleaned_data
...
else:
# Handle validation error
...
If you want to do some data formatting or validation yourself you can put this in the validation method in the form. Either for the entire form or for a form field. This is also a great way to make your code more DRY.
There are a couple of things you need to know here.
First is that generally in a Python class method you access the attributes through the 'self' object. So in theory your function should be:
def get_items(self):
return self.list.split(",")
However, in the case of a Django form, this won't work. This is because a field doesn't have a value of its own - the value is only attached to the field when it's rendered, and is obtained in different ways depending on whether the value was applied through initial data or by passing in a data dictionary.
If you have validated the form (through form.is_valid()), you can get the form via the cleaned_data dictionary:
return self.cleaned_data['list']
However this will fail if list has failed validation for any reason.
Call is_valid on the form, then access the cleaned_data dictionary.