django db lookup for datetime - database

I'm trying to filter database entries by their datetime:
models.py:
from django.db import models
class ContestEvent(models.Model):
year = models.DateTimeField()
month = models.DateTimeField()
In my view I define a function calender:
def calendar(request, pYear, pMonth):
"""
Show calendar of events for specified month and year
"""
lYear = int(pYear)
lMonth = int(pMonth)
lCalendarFromMonth = datetime(lYear, lMonth, 1)
lCalendarToMonth = datetime(lYear, lMonth, monthrange(lYear, lMonth)[1])
my_workouts = ContestEvent.objects.filter(id__year=lCalendarFromMonth, id__month=lCalendarToMonth)
lCalendar = html_calendar.WorkoutCalendar(my_workouts).formatmonth(lYear, lMonth)
Then I got the following error:
Request Method: GET
Request URL: http://127.0.0.1:8000/htmlcalendar/
Exception Type: TypeError
Exception Value:
int() argument must be a string or a number, not 'datetime.datetime'
Exception Location: C:\Python25\lib\site-packages\django\db\models\fields\__init__.py in get_db_prep_lookup, line 225
The error is the same, when I define my Model with year = models.IntegerField() instead of year = models.DateTimeField()
What is wrong here. I'm a Django Beginner.
Thank you in advance !!

I would say if you want the month and year then use IntegerField, and when you do that you no longer need to create datetime objects to pass to your filter. Try something like this:
class ContestEvent(models.Model):
year = models.IntegerField()
month = models.IntegerField()
def calendar(request, pYear, pMonth):
"""
Show calendar of events for specified month and year
"""
lYear = int(pYear)
lMonth = int(pMonth)
my_workouts = ContestEvent.objects.filter(year=lYear, month=lMonth)

Related

how to use initiate function for a cart in Django?

I'm learning Django and I'm trying to make a Cart, which the customer can get and item and add it in his/her order row and then the order will be submitted. so my teacher said use def initiate(customer), and I don't understand how to use it. Can someone please explain it to me? Thank you.
here is the code I'm working on it:
User = get_user_model()
class Customer(models.Model):
user = models.OneToOneField(User, on_delete=Product, related_name="User")
phone = models.CharField(max_length=20)
address = models.TextField()
balance = models.IntegerField(default=20000)
def deposit(self, amount):
self.balance += amount
self.save()
def spend(self, amount):
if amount > self.balance:
raise ValueError
self.balance -= amount
self.save()
class OrderRow(models.Model):
product = models.ManyToManyField(Product)
order = models.ForeignKey('Order', on_delete=models.CASCADE)
amount = models.IntegerField()
class Order(models.Model):
# Status values. DO NOT EDIT
STATUS_SHOPPING = 1
STATUS_SUBMITTED = 2
STATUS_CANCELED = 3
STATUS_SENT = 4
customer = models.ForeignKey('Customer', on_delete=models.SET_NULL)
order_time = models.DateTimeField(auto_now=True)
total_price = Sum(F('amount') * F('product__price'))
status = models.IntegerField(choices=status_choices)
#staticmethod
def initiate(customer):
Order.initiate(User)
def add_product(self, product, amount):
Order.status = 1
OrderRow.product = Product.objects.get(id=product.id)
print(product.id)
if OrderRow.objects.filter(product=product).exists():
preexisting_order = OrderRow.objects.get(product=product, order=self)
preexisting_order.amount += 1
preexisting_order.save()
else:
new_order = OrderRow.objects.create(
product=product,
cart=self,
amount=1,
)
new_order.save()
You are probably supposed to create a new Order associated with this customer. Something along the following lines:
#classmethod
def initiate(cls, customer):
return cls.objects.create(customer=customer, status=cls.STATUS_SHOPPING)
There are some other issues with your code. You cannot use SET_NULL if the fk is not nullable:
customer = models.ForeignKey('Customer', on_delete=models.SET_NULL, null=true)
There should not be multiple products per row:
class OrderRow(models.Model):
product = models.ForeignKey(Product) # not many2many!
# ...
Also, your add_product needs quite some fixing:
def add_product(self, product, amount):
self.status = self.STATUS_SHOPPING # the instance is self + use your descriptive variables
print(product.id)
# filter only rows in the current order!
if self.orderrow_set.filter(product=product).exists():
# fix naming: this is a row, not an order
preexisting_order_row = self.orderrow_set.get(product=product)
preexisting_order_row.amount += amount # why +1, you are adding amount
preexisting_order_row.save()
else:
new_order_row = OrderRow.objects.create(
product=product,
order=self,
amount=amount,
) # create saves already

ValueError: Unknown protobuf attr type <type 'datetime.date'>

Getting an error in executing the code. I have a datastore entity which has a property of type Date. An example date property value stored in an entity for a particular row is 2016-01-03 (19:00:00.000) EDT
The code i am executing is filtering the entity values based on date greater than 2016-01-01. Any idea what is wrong with the code
Error
ValueError: Unknown protobuf attr type <type 'datetime.date'>
Code
import pandas as pd
import numpy as np
from datetime import datetime
from google.cloud import datastore
from flask import Flask,Blueprint
app = Flask(__name__)
computation_cron= Blueprint('cron.stock_data_transformation', __name__)
#computation_cron.route('/cron/stock_data_transformation')
def cron():
ds = datastore.Client(project="earningspredictor-173913")
query = ds.query(kind='StockPrice')
query.add_filter('date', '>', datetime.strptime("2016-01-01", '%Y-%m-%d').date())
dataframe_data = []
temp_dict = {}
for q in query.fetch():
temp_dict["stock_code"] = q["stock_code"]
temp_dict["date"] = q["date"]
temp_dict["ex_dividend"] = q["ex_dividend"]
temp_dict["split_ratio"] = q["split_ratio"]
temp_dict["adj_open"] = q["adj_open"]
temp_dict["adj_high"] = q["adj_high"]
temp_dict["adj_low"] = q["adj_low"]
temp_dict["adj_close"] = q["adj_close"]
temp_dict["adj_volume"] = q["adj_volume"]
dataframe_data.append(temp_dict)
sph = pd.DataFrame(data=dataframe_data,columns=temp_dict.keys())
# print sph.to_string()
query = ds.query(kind='EarningsSurprise')
query.add_filter('act_rpt_date', '>', datetime.strptime("2016-01-01", '%Y-%m-%d').date())
dataframe_data = []
temp_dict = {}
for q in query.fetch():
temp_dict["stock_code"] = q["stock_code"]
temp_dict["eps_amount_diff"] = q["eps_amount_diff"]
temp_dict["eps_actual"] = q["eps_actual"]
temp_dict["act_rpt_date"] = q["act_rpt_date"]
temp_dict["act_rpt_code"] = q["act_rpt_code"]
temp_dict["eps_percent_diff"] = q["eps_percent_diff"]
dataframe_data.append(temp_dict)
es = pd.DataFrame(data=dataframe_data,columns=temp_dict.keys())
You seem to be using the generic google-cloud-datastore client library, not the NDB Client Library.
For google-cloud-datastore all date and/or time properties have the same format. From Date and time:
JSON
field name: timestampValue
type: string (RFC 3339 formatted, with milliseconds, for instance 2013-05-14T00:01:00.234Z)
Protocol buffer
field name: timestamp_value
type: Timestamp
Sort order: Chronological
Notes: When stored in Cloud Datastore, precise only to microseconds; any additional precision is rounded down.
So when setting/comparing such properties try to use strings formatted as specified (or integers for protobuf Timestamp?), not directly objects from the datetime modules (which work with the NDB library). The same might be true for queries as well.
Note: this is based on documentation only, I didn't use the generic library myself.

UUID madness with mssql

My database entry has a UUID with the value (extracted using the Microsoft SQL Server Management Studio)
CDF86F27-AFF4-2E47-BABB-2F46B079E98B
After this is loaded into my Scala application, the toString method yields this value
276ff8cd-f4af-472e-babb-2f46b079e98b
How does this happen? And how can I programmatically create a UUID instance, when I have only the bare string CDF86F27-AFF4-2E47-BABB-2F46B079E98B at hand?
Relevant Slick code (former: table definition, latter: database access object)
class ChannelTable(tag: Tag) extends Table[ChannelTuple](tag, "Channel") {
def id = column[UUID]("Id", O.PrimaryKey)
def channelId = column[Int]("Channel_Id", O.NotNull)
def timer = column[UUID]("Timer_Id", O.NotNull)
def from = column[Timestamp]("FromTime", O.NotNull)
def to = column[Timestamp]("ToTime", O.NotNull)
def mon = column[Boolean]("Mon", O.NotNull)
def tues = column[Boolean]("Tues", O.NotNull)
def wed = column[Boolean]("Wed", O.NotNull)
def thu = column[Boolean]("Thu", O.NotNull)
def fri = column[Boolean]("Fri", O.NotNull)
def sat = column[Boolean]("Sat", O.NotNull)
def sun = column[Boolean]("Sun", O.NotNull)
def * = (id, channelId, timer, from, to, mon, tues, wed, thu, fri, sat, sun)
}
object ChannelDAO extends EntityDAO[Channel, ChannelTuple] {
private val entities = TableQuery[ChannelTable]
[...]
override def get(id: UUID)(implicit session: Session): Option[Channel] = {
val y = for {
a <- entities if a.id === id
} yield (a)
if (y.list.length > 1) throw new NonUniqueResultException
y.firstOption
}
[...]
}
Slick converts a UUID to a uniqueidentifier differently then SQL Server.
endianness is unspecified in .NET / SQL Server.
Make sure to use big endian encoding for UUIDs to be consistent with the JVM if you are getting the UUID from MSSQL.
Check out this SO post. Looks like you will need to create a method to translate the UUID.
How to read a .NET Guid into a Java UUID
Works fine for me:
> val uuidString = "CDF86F27-AFF4-2E47-BABB-2F46B079E98B"
uuidString: String = CDF86F27-AFF4-2E47-BABB-2F46B079E98B
> java.util.UUID.fromString(uuidString)
res2: java.util.UUID = cdf86f27-aff4-2e47-babb-2f46b079e98b

GAE datastore: filter by date interval

I have this model:
class Vehicle(db.Model):
...
start_production_date = db.DateProperty()
end_production_date = db.DateProperty()
I need to filter, for example, all vehicles in production within, say, 2010:
I thought I could do:
q = (Vehicle.all()
.filter('start_production_date >=', datetime(2010, 1, 1))
.filter('end_production_date <', datetime(2011, 1, 1)))
buy I get BadFilterError:
BadFilterError: invalid filter: Only one property per query may have inequality filters (<=, >=, <, >)..
so, how do I acheive this? Moreover this seems to me a quite common task.
One approach is to change your model to something like this:
class Vehicle(db.Model):
...
start_production_date = db.DateProperty()
start_production_year = db.IntegerProperty()
start_production_month = db.IntegerProperty()
start_production_day = db.IntegerProperty()
end_production_date = db.DateProperty()
end_production_year = db.IntegerProperty()
end_production_month = db.IntegerProperty()
end_production_day = db.IntegerProperty()
Update these new values on every put (you could override put) and the simply:
# specific year
q = (Vehicle.all()
.filter('start_production_year =', 2010))
# specific year, different months
q = (Vehicle.all()
.filter('start_production_year =', 2010)
.filter('start_production_month IN', [1, 2, 3, 4]))
# different years
q = (Vehicle.all()
.filter('start_production_year IN', [2010, 2011, 2012]))
I went with this solution:
I set in model a ListProperty item containing all years the model was crafted:
vhl.production_years = range(start_production_date.year, end_production_date + 1)
Then test:
q = (Vehicle.all()
.filter('production_years =', 2010))

django. adding a field to Form.errors in a custom clean() method

I have an Event model that I'd like to place the following validation rule on, in a custom def clean(self): method on the Model:
def clean(self):
from django.core.exceptions import ValidationError
if self.end_date is not None and self.start_date is not None:
if self.end_date < self.start_date:
raise ValidationError('Event end date should not occur before start date.')
Which works fine, except that I'd like to highlight the self.end_date field in the admin UI, by somehow nominating it as the field that has errors. Otherwise I only get the error message that occurs at the top of the change form.
From Django 1.7 you can directly add error to the particular field by using add_error method. Django docs
form.add_error('field_name', 'error_msg or ValidationError instance')
If the field_name is None the error will be added to non_field_errors.
def clean(self):
cleaned_data = self.cleaned_data
end_date = cleaned_data.get('end_date')
start_date = cleaned_data.get('start_date')
if end_date and start_date:
if end_date < start_date:
self.add_error('end_date', 'Event end date should not occur before start date.')
# You can use ValidationError as well
# self.add_error('end_date', form.ValidationError('Event end date should not occur before start date.'))
return cleaned_data
The docs explain how to do this at the bottom.
provided example:
class ContactForm(forms.Form):
# Everything as before.
...
def clean(self):
cleaned_data = self.cleaned_data
cc_myself = cleaned_data.get("cc_myself")
subject = cleaned_data.get("subject")
if cc_myself and subject and "help" not in subject:
# We know these are not in self._errors now (see discussion
# below).
msg = u"Must put 'help' in subject when cc'ing yourself."
self._errors["cc_myself"] = self.error_class([msg])
self._errors["subject"] = self.error_class([msg])
# These fields are no longer valid. Remove them from the
# cleaned data.
del cleaned_data["cc_myself"]
del cleaned_data["subject"]
# Always return the full collection of cleaned data.
return cleaned_data
for your code:
class ModelForm(forms.ModelForm):
# ...
def clean(self):
cleaned_data = self.cleaned_data
end_date = cleaned_data.get('end_date')
start_date = cleaned_data.get('start_date')
if end_date and start_date:
if end_date < start_date:
msg = 'Event end date should not occur before start date.'
self._errors['end_date'] = self.error_class([msg])
del cleaned_data['end_date']
return cleaned_data

Resources