Django Models: error when using DateField as ForeignKey - django

Having an issue when trying to use DateField of a model class as the ForeignKey for another model class, and using default set to today on both classes. The error message is:
django.core.exceptions.ValidationError: ["'self.date' value has an invalid date format. It must be in YYYY-MM-DD format."]
code:
class DailyImage(models.Model):
date = models.DateField(auto_now_add=True, unique=True)
name = models.CharField(max_length = 1000)
image = models.CharField(max_length = 1000)
location = models.CharField(max_length = 1000)
def __str__(self):
return str(self.id) + ": " + self.name + ", " + self.location
class JournalEntry(models.Model):
date = models.DateField(auto_now_add=True)
journal = models.CharField(max_length = 5000)
image = models.ForeignKey(DailyImage, to_field='date', default='self.date')
The site is a daily journal. Each day, it adds an image from unsplash.it to the DailyImage class, which is then displayed as the header on the home page, and header on the page for the journal entry created that day. When a journal entry is created, it should automatically be referenced to the image that was created that day.
testing it in shell, the date fields seem to match, but are formatted as: datetime.date(YYYY, MM, DD)
>>> a = JournalEntry.objects.get(pk=1)
>>> a
<JournalEntry: test>
>>> a.date
datetime.date(2016, 11, 7)
>>> from journal.models import DailyImage as image
>>> b = image.objects.get(pk=1)
>>> b.date
datetime.date(2016, 11, 7)
>>> b.date == a.date
True
Any suggestions to how this should be done properly would be greatly appreciated!

a.date returns the datetime object, but you have to set the format.
t = datetime.date(2016, 11, 7)
t.strftime("%Y-%m-%d")
# '2016-11-07'
You could also set the default datetime format in settings.py
DATETIME_FORMAT = 'Y-m-d'
However I'm not sure that would be a solution in your situation.

Related

Django 'exclude' query did not return expected results

I am relatively new to Django and this is my first post in the forum.
Below are the models(simplified) that are used in the app.
The app is about reserving a set of resources for a given period.
from django.db import models
class Resource(models.Model):
id = models.AutoField(primary_key=True)
serialno = models.CharField(max_length=30, null=False, unique=True)
name = models.CharField(max_length=40, null=False)
def __str__(self):
return f"{self.name}/{self.serialno}"
class Reservations(models.Model):
id = models.AutoField(primary_key=True)
active = models.BooleanField(default=True)
name = models.CharField(max_length=30, null=False)
startdate = models.DateField(null=False)
enddate = models.DateField(null=False)
resource = models.ManyToManyField("myapp.Resource", db_table="myapp_resource_reservations", related_name="reservations")
def __str__(self):
return f"{self.name}/{self.startdate}/{self.enddate}"
For example, below are the data present in the models
Resource(format: name/serialno)
>>> Resource.objects.all()
<QuerySet [<Resource: Resource1/RES1>, <Resource: Resource2/RES2>, <Resource: Resource3/RES3>, <Resource: Resource4/RES4>]>
>>>
Reservations(format: name/startdate/enddate/active)
All reservations are made for Resource1
>>> Reservations.objects.all()
<QuerySet [<Reservations: Booking1/2023-03-01/2023-03-07/True>, <Reservations: Booking2/2023-03-15/2023-03-22/True>, <Reservations: BookingX/2023-03-08/2023-03-14/False>]>
>>>
I am trying to retrieve all resources that do not have an 'active' reservation for a given date period using below query.
>>> Resource.objects.exclude((Q(reservations__startdate__range=('2023-03-08','2023-03-14')) | Q(reservations__enddate__range=('2023-03-08','2023-03-14'))) & Q(reservations__active=True))
<QuerySet [<Resource: Resource2/RES2>, <Resource: Resource3/RES3>, <Resource: Resource4/RES4>]>
>>>
Resource1 does have a reservation: BookingX for period 2023-03-08 to 14 but it is active=False. I expected 'Resource1' to show up in above exclude query but it didn't (intended logic: 'exclude all resources that fall in the date range with an active=True reservation').
Can someone help understand why the results are not as expected ? What am I doing wrong ?
Tried using 'filter' instead of 'exclude', it behaves as expected.
>>> Resource.objects.filter((Q(reservations__startdate__range=('2023-03-08','2023-03-14')) | Q(reservations__enddate__range=('2023-03-08','2023-03-14'))) & Q(reservations__active=True))
<QuerySet []>
>>>
>>> Resource.objects.filter((Q(reservations__startdate__range=('2023-03-08','2023-03-14')) | Q(reservations__enddate__range=('2023-03-08','2023-03-14'))) & Q(reservations__active=False))
<QuerySet [<Resource: Resource1/RES1>]>
>>>
You're basically telling the ORM to exclude all Resource's that have ANY active reservations. Because & is evaluated first (before |) it doesn't really matter what is in the ranges as it has already excluded Resource 1 at that point.

Pandas/Django - Cannot convert csv saved as filefield into dataframe

I'm building a database that stores csv files and presents them when a user selects the csv he/she wants to visualize. The problem is, whenever I open the csv file from the database the resulting dataframe is garbage
models.py
class Csv(models.Model):
file_name = models.FileField(upload_to='csvs', max_length = 100)
public = models.BooleanField(default = False)
user = models.ForeignKey(User, on_delete = models.CASCADE, null = True)
name = models.CharField(max_length = 100)
library = models.CharField(max_length = 100, null = True)
def __str__(self):
return "File id: {}".format(self.id)
views.py
def test(request):
csv = Csv.objects.get(id = 5)
df = pd.DataFrame(csv.file_name)
print(df.head())
return render(request, 'mainproj/test.html', {'df' : df.dtypes})
Test_Data.csv
A header
Another header
First
row
Second
row
The print statement in views.py returns the following output that I cannot even understand and the dataframe spits out odd values for things like columns, dtypes, ect...
meanwhile
import pandas as pd
df = pd.DataFrame(pd.read_csv('Test_Data.csv'))
print(df)
returns the following as expected
Turns out the following line of code is what I needed
dataframe = pd.read_csv(io.StringIO(file_obj.read().decode('utf-8')), delimiter=',')

Filter by year and month in ndb model

what i am trying to do is that , i am using ndb model as my database and i have a model having DateTimeProperty() property.
Now what i want is that i want to fetch all the records which for a particular year and also for a particular month.
class Photo(ndb.Model):
userid = ndb.StringProperty()
source = ndb.StringProperty()
handle = ndb.StringProperty()
sourceid =ndb.StringProperty()
viewedCount = ndb.IntegerProperty(default=0)
likedCount = ndb.IntegerProperty()
uploadedOn = ndb.DateTimeProperty()
latitude = ndb.FloatProperty(default=0)
longitude = ndb.FloatProperty(default=0)
i have a field uploadedOn which has a dateTime property.
queries would be like (i) fetch all records for year 2012 (ii) fetch records for month of January
I have value in format
"uploadedOn": "2014-12-27T11:57:01"
import datetime
from_date = datetime.datetime(2015,11,30)
until_date = datetime.datetime(2016,1,1)
Photo.query(ndb.AND(Photo.uploadedOn>from_date, Photo.uploadedOn<until_date))
You can do something like:
import datetime
date_wanted = datetime.datetime(2014, 12, 27)
photo = Photo.query().filter(Photo.uploadedOn==date_wanted).fetch()

django records greater than particular date

class sales_line(models.Model):
sales_id = models.CharField(max_length=200)
item = models.CharField(max_length=200)
qty = models.IntegerField()
expected_end_date = models.DateField()
def __unicode__(self):
return self.sales_id
expected end date may be 'march 20, 2014' , 'april 29 2014' and so on,
how do i get all the records whose expected end date has crossed the current date
i have tried this :
current_date = time.strftime("%Y-%d-%m")
sales_line.objects.filter(expected_end_date__gt = current_date)
and
sales_line.objects.filter(expected_end_date__lt = current_date)
I am getting wrong data. where am i wrong???
Should the format be "%Y-%d-%m" or something like "%Y-%m-%d"? Since expected_end_date is a date field, I would use date module:
from datetime import date
today = date.today()
# or some other date:
today = date(2013, 3, 15)
sales_line.objects.filter(expected_end_date__lt=today)
The issue is that current_date is a string, while expected_end_date is a DateField. DateField cannot be compared to strings, but can be compared to python date Objects.
Try this:
from datetime import date
current_date = date.today()
sales_line.objects.filter(expected_end_date__gt = current_date)

Django Date formatting in forms query

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.