Convert CharField to String - python

For a database query with pymysql, I'm getting the model
class MyModel(Model):
id = AutoField()
date1 = CharField()
confirmed = IntegerField()
Getting the date works, but I have to do some calculations with date1. For this, I need to convert it to a datetime object with datetime.strptime().
for model in MyModel.select().where(MyModel.confirmed == 0):
rd = MyModel.date1
date_time_obj = datetime.strptime(rd, '%d.%m.%Y')
The problem is that date1 is a CharField, not a string, so strptime does not work. How can I get the content of the CharField into a string? As the rest of the script works the way it is, ideally it would be in a way that doesn't change the retrieved data.

This issue is that you're accessing the CharField from the class, rather than an instance of the class. Try this instead:
for model in MyModel.select().where(MyModel.confirmed == 0):
rd = model.date1
date_time_obj = datetime.strptime(rd, '%d.%m.%Y')

Related

Django Timezone filter returns wrong results

I wrote the following code:
date = self.request.query_params.get('date')
queryset = Fixture.objects.all().order_by('-date')
if(date):
date = pytz.utc.localize(datetime.strptime(date, "%Y-%m-%d")).astimezone(pytz.UTC)
queryset = Fixture.objects.filter(date__date=date).order_by('date')
Upon excuting this with date = "2020-09-02" the queryset returns values containing the date "2020-09-03". How come this happens and how can this be solved?
If you want to work with a date, why make it a datetime first? Your parsing could be simplified.
date = self.request.query_params.get('date')
queryset = Fixture.objects.all().order_by('-date')
if date:
date = datetime.strptime(date, "%Y-%m-%d").date()
queryset = Fixture.objects.filter(date__date=date).order_by('date')
But this parsing is also is sensitive for wrongly inserted data, and you'll get an error. Best practice imo would be creating a simple form with a DateField.
class ParseDateForm(forms.Form):
date = forms.DateField()
# This somewhere in a method
form = ParseDateForm(data=self.request.query_params)
queryset = Fixture.objects.all().order_by('-date')
if form.is_valid():
date = form.cleaned_data['date']
queryset = Fixture.objects.filter(date__date=date).order_by('date')

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())
# ^^^ ^^^

I want to store datetime in peewee.DateTimeField(), I use datetime.datetime.now() in that field as default but it can't work

this code cannot work and give json serializable error
class Bank(peewee.Model): // create Bank table
bank_id = peewee.PrimaryKeyField()
bank_name = peewee.CharField()
account_no = peewee.CharField()
ifc_code = peewee.CharField()
swift_code = peewee.CharField(null = True)
modify_date = peewee.DateTimeField(default=datetime.datetime.now(),formats=['%Y-%m-%d'])/*date in yyyy-mm-dd formate*/
status = peewee.IntegerField(default = 0)
class Meta:
database = db
This answer is very incorrect - please see my answer below (#coleifer).
The default date that you are providing is not a datetime object. Rather it's a string!
modify_date = peewee.DateTimeField(default=datetime.datetime.now().strftime('%Y-%m-%d'))
type(datetime.datetime.now().strftime('%Y-%m-%d')) --> str
You can pass default current datetime object like this:
date = datetime.datetime.now().strftime('%Y-%m-%d')
need_date = datetime.strptime(date, '%Y-%m-%d')
modify_date = peewee.DateTimeField(default=need_date)
or
peewee.DateTimeField(default=datetime.datetime.now)
It looks like non-timezone aware datetimes work fine, so if you're using UTC then you can store datetime.utcnow() as that returns the current UTC date and time with tzinfo None i.e. as a "naive" datetime object.
I found this solution to store and retrieve the timezone aware field as text, however it's not ideal as the datetime object isn't being stored.
from datetime import datetime
from peewee import *
class TimestampTzField(Field):
"""
A timestamp field that supports a timezone by serializing the value
with isoformat.
"""
field_type = "TEXT"
def db_value(self, value: datetime) -> str:
if value:
return value.isoformat()
def python_value(self, value: str) -> str:
if value:
return datetime.fromisoformat(value)
https://compileandrun.com/python-peewee-timezone-aware-datetime/
If you want to store a date, use the DateField. Also, the default needs to be a callable -- in other words, leave OFF the parentheses!
class Bank(peewee.Model): // create Bank table
bank_id = peewee.PrimaryKeyField()
bank_name = peewee.CharField()
account_no = peewee.CharField()
ifc_code = peewee.CharField()
swift_code = peewee.CharField(null = True)
modify_date = peewee.DateField(default=datetime.date.today)
status = peewee.IntegerField(default = 0)
class Meta:
database = db
When it comes time to serialize this as Json, just use a custom json formatter that can handle python datetime.date objects. This is the proper way. You should always store your data using the appropriate format and worry about presentation (and serialization) in another layer.
It is very simple to extend Python's json serializer to handle unsupported types:
def convert_date(o):
if isinstance(o, datetime.date):
return o.__str__()
json.dumps(my_obj, default=convert_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..

Why does date.today() return time as well?

In Flask, when I define a slug in a class (for mongoengine), and I want to return 2014-04-11 (YY-MM-dd), I always get YY-mm-dd hh:mm:ss as slug.
Why is it so?
When I remove the slug variable, my demo variable returns the right format...
class Post(db.Document):
demo = db.DateTimeField(default=datetime.date.today())
slug = db.DateTimeField(default=datetime.date.today())
And this is how an example URL looks like hence:
http://0.0.0.0:5000/2014-03-19%2000:00:00/
DateTimeField always returns a full date with time formated as hh:mm:ss.
To get only the date, you should change the database field to string.
This is how your class should look like hence:
class Post(db.Document):
demo = db.DateTimeField(default=datetime.date.today())
slug = db.StringFieldField(default=datetime.date.today())

Categories

Resources