Django Date formatting in forms query - django

Hi I have a model containing:
class MyModel(models.Model):
id = models.IntegerField(primary_key=True)
recorded_on = models.DateField()
precipitation = models.FloatField(null=True, blank=True)
I have a form which looks like this:
class QueryForm(forms.Form):
precipitation = forms.BooleanField(label=ugettext_lazy('Precipitation'),)
startdate = forms.DateField(widget = widgets.AdminDateWidget, label=ugettext_lazy('Start Date'),)
enddate = forms.DateField(widget = widgets.AdminDateWidget, label=ugettext_lazy('End Date'),)
In my views.py I have one view for the form and a separate view for collecting the data via GET. This is very simplified version of the second view.py:
def results(request):
if 'q' in request.GET:
...
startdate = request.GET.get('startdate', None)
enddate = request.GET.get('enddate', None)
data = MyModel.objects.filter(recorded_on__range = (startdate, enddate))
...
My date variables in GET are of the format 'YYYY-MM-DD'.
The problem is that the query raises this error:
coercing to Unicode: need string or buffer, datetime.date found
What is the best way to deal with my date format to make the query?

You'll need to create Date objects from your form data, which is currently a string. The error you're getting is from django trying to compare those strings to the dates on the models.
so:
from datetime import datetime
format = '%d-%m-%Y' # Or whatever your date format is
st = datetime.strptime(startdate, format)
ed = datetime.strptime(enddate, format)
data = MyModel.objects.filter(recorded_on__range=(st.date(), ed.date()))
Should point you in the right direction.

I am a bit confused about the error message (i.e. where does the error occur - when you make the query?).
However, I used this to convert a string from a url parameter to a datetime.date:
def things_by_appointment(request, appointment_date):
'''
Things with appointment date yyyy-mm-dd
'''
try:
as_date = datetime.datetime.strptime( appointment_date, '%Y-%m-%d').date
except ValueError:
return HttpResponseBadRequest('%s is not a correct date' % appointment_date )
things = Thing.objects.filter(
Q( appointment_date = as_date ),
#...
Althoug the string is from the path and not from the query string, it should not make a difference.

Related

Getting a query set between a range of dates Django

I'm trying to return a list of items in between 2 different dates, a date in the past and the current time using a queryset.
The error I'm getting is TypeError: an integer is required (got type str)
views.py
import datetime
import pytz
first_date = "2020-01-01 19:17:35.909424"
last_date = timezone.now()
I don't want anything returned that has a date in the future
Here is the filter in the query
.filter(hide_sentance_until=(date(first_date), date(last_date)))
This is the full queryset, but it's the above filter causing he issue
zip_flash_sentances = (
model.objects
.filter(show_sentance=True)
.filter(
hide_sentance_until=(date(first_date), date(last_date))
)
.order_by("?")
.filter(username_id = user_id_fk)
.values_list('sentance_eng', 'sentance_esp', 'id')
.first()
)
I thought it might be a comparison problem with dates but here is my model field
models.py
hide_sentance_until = models.DateTimeField(default=datetime.now(), blank=True)
Thanks
You can use gte and lte query attributes:
first_datetime = datetime.datetime.strptime(first_date, '%Y-%m-%d %H:%M:%S.%f')
last_date = timezone.now()
.filter(hide_sentance_until__lte=last_date,hide_sentance_until__gte=first_time)
One thing is that you're specifying a specific value that's determined when your code is compiled to be your default value. To have the actual current date be the value you want:
hide_sentance_until = models.DateTimeField(default=datetime.now, blank=True)
Then you need to parse the datetime out of the string.
date_value = datetime.strptime(first_date, DATETIME_FORMAT_YOU_USE)
Where DATETIME_FORMAT_YOU_USE is the series of format codes from Python that you're using.
Finally you should use the __range queryset field lookup.
.filter(
hide_sentance_until__range=(date_value, timezone.now())
)

How to combine date field and time field to store in datetime field in Django api post request?

I am Posting date and time separately and trying to save it in my Django datetime field. Here is my code:
views.py
event = Event()
start_date = request.POST['start_date']
start_time = request.POST['start_time']
event.start_timestamp = datetime.combine(start_date,start_time)
event.save()
I'd do something like this:
start_date = request.POST['start_date']
start_time = request.POST['start_time']
start_timestamp = datetime.strptime(f'{start_date} {start_time}', '%Y-%m-%d %H:%M')

Filter with 'date' in Django

In model.py, I create class Order has a field 'order_date' with DateTimeField.
In views.py, I am using this query:
orders = Order.objects.filter(order_date__date__gte = date_from, order_date__date__lte = date_to)
The Query doesn't return any data, although in the database, there are many records between date_from and date_to.
You can do that like this:
orders = Order.objects.filter(order_date__gte = date_from, order_date__lte = date_to)
You have an extra __date that you don't need, since order_date is a DateTimeField.

Filtering queryset if one value is greater than another value

I am trying to filter in view my queryset based on relation between 2 fields .
however always getting the error that my field is not defined .
My Model has several calculated columns and I want to get only the records where values of field A are greater than field B.
So this is my model
class Material(models.Model):
version = IntegerVersionField( )
code = models.CharField(max_length=30)
name = models.CharField(max_length=30)
min_quantity = models.DecimalField(max_digits=19, decimal_places=10)
max_quantity = models.DecimalField(max_digits=19, decimal_places=10)
is_active = models.BooleanField(default=True)
def _get_totalinventory(self):
from inventory.models import Inventory
return Inventory.objects.filter(warehouse_Bin__material_UOM__UOM__material=self.id, is_active = true ).aggregate(Sum('quantity'))
totalinventory = property(_get_totalinventory)
def _get_totalpo(self):
from purchase.models import POmaterial
return POmaterial.objects.filter(material=self.id, is_active = true).aggregate(Sum('quantity'))
totalpo = property(_get_totalpo)
def _get_totalso(self):
from sales.models import SOproduct
return SOproduct.objects.filter(product__material=self.id , is_active=true ).aggregate(Sum('quantity'))
totalso = property(_get_totalpo)
#property
def _get_total(self):
return (totalinventory + totalpo - totalso)
total = property(_get_total)
And this is line in my view where I try to get the conditional queryset
po_list = MaterialFilter(request.GET, queryset=Material.objects.filter( total__lte = min_quantity ))
But I am getting the error that min_quantity is not defined
What could be the problem ?
EDIT:
My problem got solved thank you #Moses Koledoye but in the same code I have different issue now
Cannot resolve keyword 'total' into field.Choices are: am, author, author_id, bom, bomversion, code, creation_time, description, id, inventory, is_active, is_production, itemgroup, itemgroup_id, keywords, materialuom, max_quantity, min_quantity, name, pomaterial, produce, product, slug, trigger_quantity, uom, updated_by, updated_by_id, valid_from, valid_to, version, warehousebin
Basically it doesn't show any of my calculated fields I have in my model.
Django cannot write a query which is conditioned on a field whose value is unknown. You need to use a F expression for this:
from django.db.models import F
queryset = Material.objects.filter(total__lte = F('min_quantity'))
And your FilterSet becomes:
po_list = MaterialFilter(request.GET, queryset = Material.objects.filter(total__lte=F('min_quantity')))
From the docs:
An F() object represents the value of a model field or annotated
column. It makes it possible to refer to model field values and
perform database operations using them without actually having to pull
them out of the database into Python memory

Django Mongoengine EmbeddedDocument query issue

my model is about a list of top movies
class Movie(Document):
title = StringField()
...
ranks = ListField(EmbeddedDocumentField('Rank'))
class Rank(EmbeddedDocument):
rank = IntField()
imdb_rating = FloatField()
date = StringField(required=True)
How can I write a query to get only the movies have Rank record in today?
I'd advise using a datetime object for date rather than a string as it seems more explicit. Either way you can easily find all Movie documents with a rank that has a date matching today like so:
Movie.objects(ranks__date__gte=datetime.today().date()) # using DateTimeField
or
Movie.objects(ranks__date="16/04/2012") # using StringField