WTForms - DateTimeLocalField data is None after submit - python

After form is submitted with a POST request, every Field data has its value, except DateTimeLocalField. Accessing DateTimeLocalField's data value is a type of None.
Form
class ArticleForm(FlaskForm):
name = StringField('Name', validators=[DataRequired()])
category = SelectField(u'Category', choices=categories.choices)
town = StringField('Town', validators=[DataRequired()])
minimal_price = IntegerField('Minimal price')
article_image = FileField('Article_image', validators=[FileRequired()])
time_left = DateTimeLocalField('Time to end', validators=[InputRequired()],
format='%Y-%m-%d %H:%M:%S')
description = TextAreaField('Description', validators=[DataRequired()])
Validation: (tested with is_submitted, all work except for article_form.time_left.data which is None)
if article_form.validate_on_submit():
new_article = Article(name=article_form.name.data,
category=article_form.category.data,
town=article_form.town.data,
minimal_price=article_form.minimal_price.data,
article_image=name,
time_left=article_form.time_left.data, # <-- None
description=article_form.description.data,
user_id=current_user.id)
Any help to get data from DateTimeLocalField ?

Try changing the format of the DateTimeLocalField from
format='%Y-%m-%d %H:%M:%S'
to:
format='%Y-%m-%dT%H:%M'
Tip: you can print the actual content of the input field prior to the validation to confirm the correct formatting of the DateTimeLocalField field.

Use wtforms.fields.html5.DateTimeLocalField instead of wtforms.DateTimeLocalField. Set the format with date and time separated by a 'T'. If you would want the current time as the default value, set default parameter.
from wtforms.fields.html5 import DateTimeLocalField
class InterviewForm(Form):
posted = DateTimeLocalField('Posted:', default=datetime.today, format='%Y-%m-%dT%H:%M')

I did extensive research on the same problem, this is a hack but I still got the timestamp from the tag which looked like:
<input id="time_left" name="time_left" required type="datetime-local" value="2018-11-15T04:44">
You basically search for the timestamp from the tag returned by the tag
date = re.search('(\d{4})[/.-](\d{2})[/.-](\d{2})[T](\d{2})[:](\d{2})',
str(form.time_left)).group())
Let me know if the solution worked for you or if found a better solution to the problem.

Related

ValueError at / time data '' does not match format '%Y-%m-%d'

I'm working on a project in which when users mention a specific date range from and to, the corresponding data gets printed. The page takes input from users through input type date when the specific date is mentioned the value of date passes to user_input_date_to and user_input_date_to. But when I'm executing I'm getting the error ValueError at / time data '' does not match format '%Y-%m-%d'
My views file
def indexview(request):
url=requests.get('https://data.covid19india.org/v4/min/timeseries.min.json')
json_data=url.json()
user_input_state=''
user_input_date_from=''
user_input_date_to=''
user_data_type=''
user_required_type=''
if request.method == 'POST':
user_input_state=request.POST.get('state')
x=request.POST['date_from']
user_input_date_to=request.POST['date_to']
user_data_type=request.POST.get('data_period')
user_required_type=request.POST.get('required_type')
#To store dates list
start_date =user_input_date_from
end_date = user_input_date_to
start_date_object = dt.datetime.strptime(start_date,"%Y-%m-%d").date()
end_date_object = dt.datetime.strptime(end_date,"%Y-%m-%d").date()
days = end_date_object - start_date_object
dates=[]
otp=[]
for i in range(days.days+1):
dates.append(str(start_date_object+dt.timedelta(days=i)))
for i in dates:
try:
otp.append(json_data[user_input_state]['dates'][i][user_data_type][user_required_type])
except KeyError:
otp.append(0)
dict_pass={
'dates':dates,
'otp':otp
}
return render(request,'index.html',dict_pass)
HTML date form
<input type="date" name="date_from"><br>
<input type="date" name="date_to">
The problem is, that you are trying to create datetime object of format '%Y-%m-%d' from the invalid user input (in your case it's empty string).
You should validate user input first, then do the business logic.
You could do it manually, or try to use existing libraries for the validation
(e.g. pydantic, marshmallow ...)

Parsing dates using WTForms Flask - Python

Hi So I've been using WTForms with success for a good period of time now.
The problem is on how to parse dates.
I've always used to assign variables according to form data as follows
firstname = form.firstname.data
This will store the user's input from the form data into my variable called "firstname", which works just fine, my problem is when it comes to dates.
I have the following code
WTForms Class
class BookingForm(Form):
start_date = DateField('Start Date', format='%m/%d/%Y')
end_date = DateField('End Date', format='%m/%d/%Y')
The booking route
#app.route('/book/', methods=['GET','POST'])
#login_required
def book():
try:
form = BookingForm(request.form)
if request.method == "POST" and form.validate():
start_date = form.start_date.data
end_date = form.end_date.data
# I Have also tried form.start_date.data.strftime('%m-%d-%Y') with no luck
...
The HTML Template {jinja}
<div class="col-md-4">
{{ render_date_field(form.start_date) }}
</div>
<div class="col-md-4">
{{ render_date_field(form.end_date) }}
</div>
I am also using datetime in python
from datetime import datetime
I've been trying to follow many docs on how to parse a date into a variable from a user input form with no luck, Does anybody know the right syntax?
Thanks
form.date_created.data returns a datetime.date object.
The month, day, and year attributes store these values as integers. There is no need to import the datetime to solve this problem.
You can use date.strftime('%m-%d-%y') to get a string representation such as "10-22-18".
form = BookingForm(request.form)
if request.method == "POST" and form.validate():
start_date = form.start_date.data
end_date = form.end_date.data
# print(type(start_date)) -> <class 'datetime.date'>
start_month = start_date.month
start_day = start_date.day
start_year = start_date.year
start_date_str = start_date.strftime('%m-%d-%y')
# and so on...
Take a look at the WTForms Documentation for DateField.
class wtforms.fields.DateField(default field arguments, format='%Y-%m-%d')
Same as DateTimeField, except stores a datetime.date.
You can check out more about the date object in the docs
Python Docs
Tip: if you had tried print(type(start_date)) to see what it prints, you probably would have figured it out on your own.

Django view objects filter with timezone.now().date or timezone.now().time-> expected string or bytes-like object

Hi i have some Django 11 project, my model look like
class Event(models.Model):
name = models.CharField(max_length=100, unique=True)
title = models.CharField(max_length=100)
info = models.CharField(max_length=100)
image = models.ImageField(upload_to='events/%Y/%m/%d')
start_date = models.DateField(default=timezone.now)
start_time = models.TimeField(default=timezone.now)
stop_date = models.DateField(default=timezone.now)
stop_time = models.TimeField(default=timezone.now)
place = models.ForeignKey('places.Place', on_delete=models.CASCADE)
company = models.ForeignKey('companies.Company', on_delete=models.CASCADE)
and my view look like
def place_website(request, place_id):
place_template = get_template('room.html')
place_obj = Place.objects.filter(id=place_id)
# filter for event obejts only for requested place, filtered for now and next events
place_event_now = Event.objects.filter(place=place_id, start_date=timezone.now().date, stop_date__gte=timezone.now().date)
place_events_next = Event.objects.filter(place=place_id, start_date=timezone.now(), stop_date__gte=timezone.now()).order_by('start_time')
place_context = {
'place_obj': place_obj,
'place_event_now': place_event_now,
'place_events_next': place_events_next,
}
return HttpResponse(place_template.render(place_context))
the thing i want to manage is to pass to template the list of filtered Event objects based on time.
Lets pick this line
place_event_now = Event.objects.filter(place=place_id, start_date=timezone.now().date, stop_date__gte=timezone.now().date)
it couse error "expected string or bytes-like object" but when i remove ".date" from "timezone.now()" error disappear (then filter do nothing) but i want to compare date to date and time to time.
How to do this properly ?
This approach to filter objects in view rather than in template is proper?
###### UPDATE ########
Its werid because after correction now i have no error but queryset is not filtered properly, look like only two first parameter is filtering ok and the another two is causing empty queryset.
place_event_now = Event.objects.filter(place=place_id, start_date=timezone.now().strftime('%Y-%m-%d'), start_time__lte=timezone.now().strftime('%H:%M:%S'), stop_time__gte=timezone.now().strftime('%H:%M:%S'))
I my database time is saved in format H:M:S and timezone.now().time() has different format so i modified filter with .strftime this didnt help, what i wont is to limit "place_event_now" queryset to particular object/objects that come true with condition start_time < currenttime < stop_time.
Another case is with place_event_next
place_events_next = Event.objects.filter(place=place_id, start_date=timezone.now().strftime('%Y-%m-%d'), stop_date__gte=timezone.now().strftime('%Y-%m-%d'), start_time__gt=timezone.now().strftime('%H:%M:%S')).order_by('start_time')
Event when i filter objects that start_time is greater than timezone.now() they still are in queryset.
Am I doing something wrong ?
I figured it out that timezone.now() return time not in my current timezone, i change it to timezone.localtime() and everything working perfect !!!
May be you need call date to date()
replace
filter(place=place_id, start_date=timezone.now().date, stop_date__gte=timezone.now().date)
# ^^^ ^^^
to
filter(place=place_id, start_date=timezone.now().date(), stop_date__gte=timezone.now().date())
# ^^^ ^^^

Map multiple WTForm fields to one attribute using Flask-WTForm

I have a form that maps correctly to my model. What I want to do is have users input their date of birth using three SelectField (day, month, year) and write the combination of those three values to my model.dateOfBirth. I know of the existing DateField and DateTimeField options, but neither of them are suitable.
I've attempted this using a FormField but it fails when I call populate_obj on the whole Form 'str' object has no attribute 'day', assuming that it is trying to set model.dateOfBirth.day which of course, doesn't exist.
I can pull all the relevant data from form.data and write to model outside of populate_obj, but I can't seem to remove the dateOfBirth data to stop populate_obj from failing. There are of course other questions about how I could prefill the form data when passing obj on form creation, but I'm willing to sacrifice that for now.
I've looked at using a FieldList, but the docs say that it gives all its data back in a list, instead of a dict, which will still give me the same issues
Forms
class DOBForm(Form):
day = SelectField(u'Please enter your date of birth',
choices=days,
validators=[InputRequired(message=u' ')]
)
month = SelectField(u' ',
choices=months,
validators=[InputRequired(message=u' ')]
)
year = SelectField(u' ',
choices=years,
validators=[InputRequired(message=u' ')]
)
and
class MainForm(Form):
dateOfBirth = FormField(DOBForm)
Model
class Model
dateOfBirth = db.Column('dateOfBirth', Date)
You can write a function for this.
from datetime import datetime
def date_of_birth(**kwargs):
day = kwargs['day']
month = kwargs['month']
year = kwargs['year']
strip="-"
seq = (day,month,year)
date = datetime.strptime(strip.join(seq) , '%d-%m-%Y')
birthday = stringDate.strftime('%d-%m-%Y')
dob = Model()
dob.dateOfBirth = birthday
session = Session()
session.add(dob)
session.commit()
retval = row2dict(dob)
session.close()
return retval
Now you can call this function.
I don't test this function yet. If you get any error or have any query , let me know..

Validation Error in Python Django

I have HTML form with one optional field like this
<input type="number" name="total_amount" id="total_amount" class="completedtype" onchange="add()"/>
When I input some number in the field then I the whole form data gets saved in to the database. But when there is no data then I get Validation Error
ValidationError at /oms_data/ [u"'' value must be a decimal number."]
I have tried to resolve this issue for more than half a day but nothing helped me. I have tried the following to resolve this error.
I have used something like this which was suggested in some SO answer:
total_amount = request.POST.get("total_amount",0) ## get total_amount or take default value 0
That didn't work so I used the famous try: except: as shown below:
try:
total_amount = request.POST["total_amount"]
except: ## whatever the exception and not just Validation Error
total_amount = 0
I don't know why none of this worked.The error occurs when trying to save the form.
save_Order_Selling_Pricing = models.Order_Selling_Pricing(order_id=order_id,vendor_name = vendor_name,total_amount =total_amount,
vendor_discount_percent=vendor_discount_percent,dg_percent = dg_percent,
vendor_discount_amount=vendor_discount_amount,vendor_percent = vendor_percent,
dg_discount_percent = dg_discount_percent,dg_discount_amount=dg_discount_amount,
final_selling_price = final_selling_price,order_selling_pricing_id=order_selling_pricing_id,
order_payment_mode = order_payment_mode,present_datetime=present_datetime)
save_Order_Selling_Pricing.save()
Any help in this regard would be great!
Thanks in advance! I'm using Django 1.8 python 2.7 if this helps.
UPDATE 1:
I have my models defined as shown below:
total_amount = models.DecimalField(max_digits=10,decimal_places=2,blank = True,null = True,default = Decimal('0.00'))

Categories

Resources