I have the following model property:
#property
def is_complete(self):
return datetime.datetime.now() >= datetime.datetime.combine(self.date, self.ending_time)
I was wondering, how could I convert this to an annotation, such that:
MyObject.objects.annotate(is_complete=?).filter(is_complete=True)
Would be equiavalent and valid?
You could use ExpressionWrapper to combine the date and time, convert the result to python actual datetime object and finally you can make the comparison.
from django.db.models import DateTimeField, ExpressionWrapper, F
from django.utils import timezone
MyCustomObject.objects.annotate(combine_datetime=ExpressionWrapper(F('date') + F('ending_time'), output_field=DateTimeField())).filter(combine_datetime__lte=timezone.now())
Docs: Django 2.2 Query Expression F with anotation
Try this :
from django.db.models.expressions import Value
from django.db.models.functions.datetime import TruncDate
MyObject.objects.annotate(is_complete=Value(datetime.datetime.now() >= datetime.datetime.combine(TruncDate('date'),TruncDate('ending_time'))))).filter(is_complete=True)
Related
to be brief, i have this queryset:
monthly_revenue = list(Booking.objects.annotate(month=Month('created_at'))
.values('month')
.annotate(total=Sum('price'))
.order_by('month'))
this is what it is returning:
[{'month': 11, 'total': Decimal('4550.00')}]
the result is going to a js script to show a graph, and i need to remove the Decimal() prefix.
Any help or hint is appreciated.
If you just want to remove "Decimal" prefix you could just define a specific output field in your annotation:
monthly_revenue = list(Booking.objects.annotate(month=Month('created_at'))
.values('month')
.annotate(total=Sum('price', output_field=FloatField()))
.order_by('month'))
Since you're using Django you can use DjangoJSONEncoder as follows:
from django.core.serializers.json import DjangoJSONEncoder
my_dict = [{'month': 11, 'total': Decimal('4550.00')}]
json_result = json.dumps(my_dict, cls=DjangoJSONEncoder)
But, keep in mind that DjangoJSONEncoder turns decimal into strings so the result would be:
[{"month": 11, "total": "4550.00"}]
If you navigate to DjangoJSONEncoder source code you find this:
elif isinstance(o, (decimal.Decimal, uuid.UUID, Promise)):
return str(o)
you could convert it to a type float, like this
monthly_revenue = list(Booking.objects.annotate(month=Month('created_at'))
.values('month')
.annotate(total=float(Sum('price')))
.order_by('month'))
I finally found two solutions that worked for me:
Thanks to #Ramy's answer, I overidden the DjangoJSONEncoder, to support the conversion of a Decimal to a float:
import decimal
import uuid
from django.utils.functional import Promise
from django.core.serializers.json import DjangoJSONEncoder
class JsonDecimalToFloatEncoder(DjangoJSONEncoder):
def default(self, o):
if isinstance(o, (decimal.Decimal, uuid.UUID, Promise)):
return float(o)
return super().default(o)
and I used it as he mentioned:
monthly_revenue = list(Booking.objects.annotate(month=Month('created_at'))
.values('month')
.annotate(total=Sum('price'))
.order_by('month'))
json_result = json.dumps(monthly_revenue,cls=ExtendedEncoder)
json_result
'[{"month": 11, "total": 4550.0}]'
this solution requires more work on the server side, so i opted for the second solution of #rossi which does more work on the database rather than the server, and that's what the django's documentation suggest.
from django.db.models import FloatField
from django.db.models.functions import Cast
list(Booking.objects.annotate(month=Month('created_at'))
.values('month')
.annotate(total_as_f=Cast('total',
output_field=FloatField()))
.order_by('month'))
[{'month': 11, 'total': Decimal('4550.00'), 'total_as_f': 4550.0}]
hope this will help anyone in the futur.
Here is the datetime string:
dt = '2016-04-07 23:00:00'
I have tried datetime.strptime(year+"-"+day+"-"+month+" "+hour+":"+mins+":"+"00", '%Y-%d-%m %H:%M:%S') but I get this error:
type object 'datetime.datetime' has no attribute 'datetime'
from dateutil import parser
date_string = '2016-04-07 23:00:00'
date_object = parser.parse(date_string)
change
from datetime import datetime
to
import datetime
and try this. hope this helps..
import datetime
datetime.datetime.strptime(dt, "%Y-%m-%d %H:%M:%S")
We are making a Pc builder compare website, so you can compare pc components prices and make a cheap pc. We are using external data with Scrapy that saves it into MongoDB, we use Django as framework.
I have a 'prijs' Array (price) of an object as unicode, this object is in the QuerySet. I want that each 'prijs' in that array is a Float instead of unicode. Is there some way to convert the unicode array to a normal float array. I Googled alot but no solution for me, I hope you can help me with our problem.
Sorry for my bad English, thanks in advance!
Here is one object of MongoDB:
> db.processoren.findOne()
{
"_id" : ObjectId("547db39af2125f612cb8a1e5"),
"info" : [
"Quad-core, Inclusief koeler"
],
"sku" : [
"BX80646I54590"
],
"prijs" : [
"188.00000000000000000000"
],
"categorie" : "processoren",
"herkomst" : "paradigit",
"naam" : [
"Intel Core i5-4590 - 3.3GHz - Socket 1150"
],
"link" : "http://www.paradigit.nl/intel-core-i5-4590-3-3ghz-socket-1150/80015736/details.aspx",
"stock" : [
"Op dit moment niet beschikbaar"
]
}
models.py
from django.db import models
from mongoengine import *
from APc.settings import DBNAME
connect(DBNAME)
class Processoren(Document):
herkomst = StringField(max_length=200)
categorie = StringField(max_length=120)
naam = StringField(max_length=500)
subnaam = StringField(max_length=500)
info = StringField(max_length=500)
prijs = FloatField()
stock = StringField(max_length=500)
ean = StringField(max_length=200)
sku = StringField(max_length=200)
herkomst = StringField(max_length=200)
link = StringField(max_length=200)
views.py
from django.shortcuts import render_to_response
from django.template.loader import render_to_string
from django.shortcuts import HttpResponseRedirect
from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger
from django.template import RequestContext
from django.template import loader
from django.http import HttpResponse
from bson.json_util import dumps
from pcbuilder.compatibility import *
from pcbuilder.filters import *
import json as simplejson
from models import Processoren, Moederborden, Koeling, Behuizingen, Grafische, Harde, Dvd, Geheugen, Voeding
from itertools import chain
import json
def processoren(request):
processorenlijst = Processoren.objects
print type(processorenlijst[0].prijs[0])
This is the output of the print
<type 'unicode'>
You can easily convert a list of strings to floats by doing something like below.
unicode_list = [u'10', u'20', u'123.1']
[float(val) for val in unicode_list]
I've never used MongoDB but I know in db backends like MySQL and PSQL you enforce types. The ORM will then return the values as the correct types. Perhaps the real issue is the structure of your data.
I'm a Django newbie,
I am following a tutorial and I had to create two models shown below:
import datetime
from django.db import models
from django.utils import timezone
class Poll(models.Model):
question = models.CharField(max_length=200)
pub_date = models.DateTimeField('date published')
def __unicode__(self):
return self.question
def was_published_recently(self):
return self.pub_date >= timezone.now() - datetime.timedelta(days=1)
class Choice(models.Model):
poll = models.ForeignKey(Poll)
choice_text = models.CharField(max_length=200)
votes = models.IntegerField()
def __unicode__(self):
return self.choice_text
The following code is from the tutorial. I should get True.
# Make sure our custom method worked.
>>> p = Poll.objects.get(pk=1)
>>> p.was_published_recently()
True
But when I type (same lines as tutorial):
>>> p = Poll.objects.get(pk=1)
>>> p.was_published_recently()
I get the following error message:
models.py line 12 in was_published_recently
NameError: global name 'datetime' is not defined..
I imported datetime and timezone... I don't see why I get that error message.
Any help will be appreciated! :-)
You need to import Timezone first from Django utils and after that you need to import datetime.
from django.db import models
from django.utils import timezone
import datetime
Couldn't reproduce the problem, your code works for me.
You could try with something like this:
from datetime import timedelta as tdelta
...
def was_published_recently(self):
return self.pub_date >= timezone.now() - tdelta(days=-1)
In the tests tutorial (part 5), we work on the polls/tests.py file. However, when you run the test, the error complains about the polls/models.py file. This file isn't mentioned in the tests tutorial but you can see it in the error message.
Add from django.utils import timezone to the polls/models.py and try the test again.
If your problem is about Writing your first Django app, part 5, you should add these two lines
import datetime
from django.utils import timezone
Just for clarification this is what I needed to add at the top of my polls/models.py file:
import datetime
from django.utils import timezone
I know this is an older thread. I had the same problem because I forgot to add this line:
from django.utils import timezone
About that error message, please note what Django docs say:
If you encounter an exception querying dates or times, please try installing it before filing a bug. >It’s as simple as:
$ sudo pip install pytz
Once you install the package, the problem will magically go away!
I tried all the things but the problem was still not getting solved. In the end the test worked when I also imported in the same order as mentioned by other in the shell too.
I had to import datetime in the end and only after that it started working.
I got the same issue.
I found out that the Python shell must be reopened after adding import of timezone so the changes would be applied. After that it worked for me.
Desciption:
I have a generic function
def gen(model_name,model_type):
objects = model_name.objects.all()
for object in objects:
object.model_type = Null (Or some activity)
object.save()
How Can I achieve the above ? Is it possible?
I would use get_model:
from django.db.models import get_model
mymodel = get_model('some_app', 'SomeModel')
As of Django 1.7 the django.db.models.loading is deprecated (to be removed in 1.9) in favor of the the new application loading system. The 1.7 docs give us the following instead:
$ python manage.py shell
Python 2.7.6 (default, Mar 5 2014, 10:59:47)
>>> from django.apps import apps
>>> User = apps.get_model(app_label='auth', model_name='User')
>>> print User
<class 'django.contrib.auth.models.User'>
>>>
if you pass in 'app_label.model_name' you could use contenttypes e.g.
from django.contrib.contenttypes.models import ContentType
model_type = ContentType.objects.get(app_label=app_label, model=model_name)
objects = model_type.model_class().objects.all()
The full answer for Django 1.5 is:
from django.db.models.loading import AppCache
app_cache = AppCache()
model_class = app_cache.get_model(*'myapp.MyModel'.split('.',1))