unixtimestamp input in DataTimeField - django

Per specification I have date and time input in UnixTimeStamp Also, I need check that I have only digits on input (nor something like this "2011-12-12")
I have forms.DataTimeField and model.DataTimeField now.
I decided to modify this in such way:
Added UnixTimeStampField(forms.RegexField) - here I check with regular expression, that I have only digits.
But I got problem with model, since UnixTimeStampField(forms.RegexField) is based on string and need to be converted to datatime.
I don't like this solution.
How I can create something like UnixTimeStampField(forms.DateTimeField)?
I tried to do this, but then I have "123321" on input I got "Incorrect parameter" from DateTimeField validators.

You don't need a custom model and/or form field for this. Just use the built-in forms.DateTimeField and models.DateTimeField, then add the following settings to your settings.py:
DATETIME_FORMAT = "U"
DATETIME_INPUT_FORMATS = ("%s",)
Read more about this settings here.

Related

Django how to use model DecimalField with additional character values?

I have an input box that must accept the following parameters:
Empty Value ('')
ZERO (0)
Fail value ('x')
I know that I can create a custom "fail" BooleanField that gets set to True if "x" is typed. However, I would like to know if it is possible add these values inside the DecimalField. Maybe, use CharField with Decimal Validation. However, trying to use it with CharField and Decimal Validation failed. So, I am not sure how else I can achieve this.
Thanks!
Could you do something with validators like:
extended_decimal_field = models.CharField(
max_length=10,
validators=[RegexValidator('^\d{8}[.]{1}\d{2}|['X']{1}$')]
)
I don't think this is exactly right but might be right track?

Convert the value of a field in a django RawQueryset to a different django field type

I have a rather complex query that's generating a Django RawQuerySet. This specific query returns some fields that aren't part of the model that the RawQuerySet is based on, so I'm using .annotate(field_name=models.Value('field_name')) to attach it as an attribute to individual records in the RawQuerySet. The most important custom field is actually a uuid, which I use to compose URLs using Django's {% url %} functionality.
Here's the problem: I'm not using standard uuids inside my app, I'm using SmallUUIDs (compressed UUIDs.) These are stored in the database as native uuidfields then converted to shorter strings in python. So I need to somehow convert the uuid returned as part of the RawQuerySet to a SmallUUID for use inside a template to generate a URL.
My code looks somewhat like this:
query = "SELECT othertable.uuid_field as my_uuid FROM myapp_mymodel
JOIN othertable o ON myapp_mymodel.x = othertable.x"
MyModel.objects.annotate(
my_uuid=models.Value('my_uuid'),
).raw(query)
Now there is a logical solution here, there's an optional kwarg for models.Value called output_field, making the code look like this:
MyModel.objects.annotate(
my_uuid=models.Value('my_uuid', output_field=SmallUUIDField()),
).raw(query)
But it doesn't work! That kwarg is completely ignored and the type of the attribute is based on the type returned from the database and not what's in output_field. In my case, I'm getting a uuid output because Postgres is returning a UUID type, but if I were to change the query to SELECT cast othertable.uuid_field as text) as my_uuid I'd get the attribute in the format of a string. It appears that Django (at least version 1.11.12) doesn't actually care what is in that kwarg in this instance.
So here's what I'm thinking are my potential solutions, in no particular order:
Change the way the query is formatted somehow (either in Django or in the SQL)
Change the resulting RawQuerySet in some way before it's passed to the view
Change something inside the templates to convert the UUID to a smalluuid for use in the URL reverse process.
What's my best next steps here?
A couple of issues with your current approach:
Value() isn't doing what you think it is - your annotation is literally just annotating each row with the value "my_uuid" because that is what you have passed to it. It isn't looking up the field of that name (to do that you need to use F expressions).
Point 1 above doesn't matter anyway because as soon as you use raw() then the annotation is ignored - which is why you see no effect coming from it.
Bottom line is that trying to annotate a RawQuerySet isn't going to be easy. There is a translations argument that it accepts, but I can't think of a way to get that to work with the type of join you are using.
The next best suggestion that I can think of is that you just manually convert the field into a SmallUUID object when you need it - something like this:
from smalluuid import SmallUUID
objects = MyModel.objects.raw(query)
for o in objects:
# Take the hex string obtained from the database and convert it to a SmallUUID object.
# If your database has a built-in UUID type you will need to do
# SmallUUID(small=o.my_uuid) instead.
my_uuid = SmallUUID(hex=o.my_uuid)
(I'm doing this in a loop just to illustrate - depending on where you need this you can do it in a template tag or view).

set input to AM PM in django timefield

i want to allow users to be able to choose between am and pm with my django timefield
Currently if I enter:
11:00 AM
, i get a form error: "Enter a valid time."
If I enter:
11:00
the form validates with no problem.
I also tried:
class RemindersForm(forms.ModelForm):
remdinder = forms.TimeField(input_formats='%H:%M %p',)
class Meta:
model = NotificationPreference
fields = (
'reminder',
)
This changes the input format to:
11:00:00
and still gives me the above validation error.
What am I doing wrong?
I was searching for a similar answer and I didn't find a suitable one for models.TimeField, so, the easiest solution that I found for doing this site wide would be to setting in your settings.py the following global variable:
TIME_INPUT_FORMATS = ['%I:%M %p',]
I hope this helps someone.
To use other formats see:
https://docs.python.org/3/library/datetime.html#strftime-strptime-behavior
To get a 12hr time format you would use the following:
For input (This is the list of formats Django uses in validation):
field = TimeField(input_formats=('%I:%M %p',...,...))
For output (This is the format Django will use to display time values):
field = TimeField(widget=TimeInput(format='%I:%M %p'))
The %I indicates a 12 hour clock format whereas the %H indicates a 24 hour clock format.
Additionally, the default list of input_formats can be found in each locales formats.py file. Django uses the first format in the input_formats list as the default output format for time fields.
I think you can do some thing like this in forms.py
field = DateTimeField(input_formats='%H:%M %p',...)
According to the Django documentation, and python's datetime docs, it should work if you change the time input settings to:
TIME_INPUT_FORMATS = ('%I:%M %p',)

How do I search a db field for a the string after a "#" and add it to another db field in django

I want to have a content entry block. When a user types #word or #blah in a field, I want efficiently search that field and add the string right after the "#" to a different field as a n entry in a different table. Like what Twitter does. This would allow a user to sort by that string later.
I believe that I would do this as a part of the save method on the model, but I'm not sure. AND, if the #blah already exists, than the content would belong to that "blah"
Can anyone suggest samples of how to do this? This is a little beyond what I'm able to figure out on my own.
Thanks!
You can use regex (re) during save() or whenever to check if your field text contains #(?P<blah>\w+) , extract your blah and and use it for whatever you want .

Django changes field types on query results (!)

I have the following model
class MonitorData(models.Model):
[... other stuff]
starttime = models.CharField(max_length=64, db_column='spurlStartTime', blank=True)
So, the starttime is a char field (in the database, it represents a datetime column)
Now, here's what I am doing:
oo=models.MonitorData.objects.all()
print oo[0].starttime
print type(oo[0].starttime)
And here's what I am getting:
00:35:59
<type 'datetime.time'>
For my own reasons (don't want to discuss them) I want to read it as a varchar and then parse it myself. But django is NOT allowing me to do that because, for reasons unknown to me, it converts that to a datetime !!!
Can anybody explain to me why django has that behaviour and how can I get my precious strings back ? Is there a way to force django cast this value as string ?
ps: I know how to use str() so pls don't answer me that
Django hasn't done anything to it. The DBAPI adapter sees that it's a DATETIME and therefore returns a datetime. And there's nothing in CharField that forces a datetime to text.
I think,
Instead of saving the value in the datetime format. Try to save it in the isoformat. You can convert easily.