Calculate date from last operation from 90 days after - python

I need to calculate 90 day after last operation in user's cart!
I have model model ORDERING
class Order(DirtyFieldsMixin, models.Model):
...
items_add_date = models.DateTimeField(null=True, blank=True)
...
my task is. Track the date when user added last item in his own cart and then, if past 90 days and user not added any more items in cart sent to him email.
I'm doing this
def cart_add(request):
...
order.items_add_date = datetime.datetime.now()
order.save()
...
But what and how should I act after?

Not sure what you are struggling with but if you need to determine if its been 90 days then you would add a check:
#query for order
order = Order.get(xxx)
ninety = datetime.datetime.now() - timedelta(days=-90)
if order.items_add_date < ninety:
#send email
If you need to query for things older than 90 days:
order = Order.filter(items_add_date__lt=ninety)

I solved it so
srok = datetime.datetime.now()-timedelta(minutes=1)
user_unbuying = Order.objects.filter(items_add_date__lt=srok)
usr=[]
for unbus in user_unbuying:
if unbus.customer.id not in usr:
if unbus.customer is not None:
if unbus.items_add_date is not None:
usr.append(unbus.customer.id)
#send mail

Related

Python/Django date query: Unsupported lookup 'date' for DateField or join on the field not permitted

I have a simple method. Entries are entries in a time sheet application where employees enter their hours.
class Entry(m.Model):
""" Represents an entry in a time_sheet. An entry is either for work, sick leave or holiday. """
# type choices
WORK = 'w'
SICK = 's'
VACATION = 'v'
type_choices = (
(WORK, 'work'),
(SICK, 'sick leave'),
(VACATION, 'vacation'),
)
# meta
cr_date = m.DateTimeField(auto_now_add=True, editable=False, verbose_name='Date of Creation') # date of creation
owner = m.ForeignKey(User, editable=False, on_delete=m.PROTECT)
# content
type = m.CharField(max_length=1, choices=type_choices, default='w')
day = m.DateField(default=now)
start = m.TimeField(blank=True) # starting time
end = m.TimeField(blank=True) # ending time
recess = m.IntegerField() # recess time in minutes
project = m.ForeignKey(Project, on_delete=m.PROTECT)
#classmethod
def get_entries_for_day(cls, user, day):
""" Retrieves any entries for the supplied day. """
return Entry.objects.filter(day__date=day, owner=user).order_by('start')
However, when I try to run my project like this, it terminates with the following error code:
"Unsupported lookup 'date' for DateField or join on the field not
permitted."
I don't quite understand the message. The specified field is a date field which has no further restrictions. Any hints would be appreciated.
There's no such thing as a __date lookup on a DateField; the field is already a date.
It's not clear what you are trying to compare this field with. Is the day you are passing into that method an integer, or a date? If it's also a date then you should just compare them directly.
I'm facing an issue with Django-filters, The filter was not taking the same date range while I was using it. so I added date__lte/gte in lookup_expr.something like this.
from_date = django_filters.DateFilter(field_name="created_at", lookup_expr='date__gte')
to_date = django_filters.DateFilter(field_name="created_at", lookup_expr='date__lte')

How do i compare the sum of two fields to another field on the same model in Django

Here is my model
class Wallet(models.Model):
"""
Keep track of the monetary values of a company's wallet
"""
serializer_class = WalletSocketSerializer
company = models.OneToOneField(Company, verbose_name=_('company'))
packaged_credits = models.BigIntegerField(_('packaged credits'), default=0)
purchased_credits = models.BigIntegerField(_('purchased credits'), default=0)
low_credits_threshold = models.BigIntegerField(default=0)
Now i would like to send an alert if the total credits are less than the threshold, this would be the equivalent of getting all low wallets in this SQL
select * from wallets_wallet where (packaged_credits + purchased_credits) < low_credits_threshold;
I want to know how to execute that in django, right now i have tried the following, it works, but i think it should be done in a more Django way:
low_wallets = []
for wallet in Wallet.objects.all():
if wallet.packaged_credits + wallet.purchased_credits < wallet.low_credits_threshold:
low_wallets.append(wallet)
from django.db.models import F
low_wallets = Wallet.objects.filter(
low_credits_threshold__gt=F('packaged_credits')+F('purchased_credits')
)
Wallet.objects.extra(where=["packaged_credits + purchased_credits < low_credits_threshold"])

return all objects associated with a user

how can I get objects that are associated with a user
I am creating this app for managing/tracking customers
I have form which is used to save customer personal info and another field which is how much they are willing to spend + We can assign the customer to a user to be dealt with.
e.g. user1 assigned to customer1, customer2, customer3
I want to get one amount they willing to spend from all customers assigned to user1
So for example something like this
[<user1: <customer1:$10> <customer2:$100> <customer3:$1000>]
And then sum the prices together so something like this [<user1: total:$1110>]
this is what I done but doesn't seem to work
annual_spend = Lead.objects.filter(assign_to=User).exclude(lead_status='converted').aggregate(Sum('annual_spend'))
How could I do this any ideas?
For specific user:
this_user = User.objects.get(id=ENTER USER ID HERE)
annual_spend['annual_spend__sum'] = Lead.objects.filter(assign_to=this_user).exclude(lead_status='converted').aggregate(Sum('annual_spend'))
or if you want it for the user that is authenticated:
annual_spend['annual_spend__sum'] = Lead.objects.filter(assign_to=request.user).exclude(lead_status='converted').aggregate(Sum('annual_spend'))
grand total for all Lead instances:
annual_spend['annual_spend__sum'] = Lead.objects.all().exclude(lead_status='converted').aggregate(Sum('annual_spend'))
For a table with value for each user:
all_users = User.objects.all()
values = {}
for this_user in all_users:
values[this_user.id] = Lead.objects.filter(assign_to=this_user).exclude(lead_status='converted').aggregate(Sum('annual_spend'))['annual_spend__sum']

F() Expression strange behavior with Django

I have this template tag that ultimately returns a list of 'active' advertisements (checks if Campaign with the active field is True, then pulls ads from the Campaign with a queryset)
#register.assignment_tag
def get_current_campaigns(amount):
# Get all the campaigns that are active
current_campaigns = Campaign.objects.filter(active=True)
current_campaigns_count = current_campaigns.count()
# To avoid the list index being out of range and throwing an IndexError
# We reduce the amount to match the amount of rows in the model if the
# amount of rows is less than the amount being requested.
if amount > current_campaigns_count:
amount = current_campaigns_count
# Select active campaigns randomly
random_camps = []
for i in range(amount):
random_camps.append(random.choice(current_campaigns))
# prepare all the ads to return
output = []
for campaign in random_camps:
# get all the ads that a campaign has
ads = campaign.advertisement_set.all()
# now select one randomly
ad = random.choice(ads)
# hand it to output
output.append(ad)
# mark that this campaign has been seen
campaign.impressions = F('impressions') + 1
campaign.save()
# checks and sets if the campaign is still active
campaign.check_active()
return output
And here is the Model that goes with it:
class Campaign(models.Model):
''' Represents an Advertisement Campaign '''
title = models.CharField(max_length=50, blank=True, verbose_name='Campaign Title')
impressions = models.IntegerField()
impression_limit = models.IntegerField()
created = models.DateTimeField(auto_now_add=True)
active = models.BooleanField(default=False)
def check_active(self):
''' Checks if the Campaign is currently active '''
if self.impressions >= self.impression_limit:
self.active = False
self.save()
The strange bit: Every time I visit the page the ad is on and then check it in the admin, the object impressions goes up by 2 (it should be 1) and gets marked as False, even if this if self.impressions >= self.impression_limit isn't true, it still somehow changes the active field to being False regardless.
Any clue why this strange behavior is happening? I can provide more info if needed.
random.choice does not guarantee to produce non-repeating items.
import random
random_camps = random.sample(current_campaigns, amount)
is the way to go here.
Update
If you're worried about the speed, this question addresses quick random row selection in postgres.

Processing django models

I am trying to process a query from my database of model TradeOrder:
class TradeOrder(models.Model):
#denoted in 2 three letter tickers with underscore such as anc_btc
pair = models.CharField(max_length=50)
#buy_order or sell_order
order_type = models.CharField(max_length=50)
#number e.g. .3455 or .190
trade_rate = models.PositiveIntegerField()
trade_amount = models.PositiveIntegerField()
#name of the account
trade_order_account = models.CharField(max_length=50)
def __str__(self):
return '%s %s %s %s %s' % (self.pair, self.order_type, self.trade_rate, self.trade_amount, self.trade_order_account)
when i execute under views.py for my app
buyorders=TradeOrder.objects.filter(pair="anc_btc", order_type="buy_order")
i get a list that looks like this:
[<TradeOrder: anc_btc buy_order 7987 7897 a>, <TradeOrder: anc_btc buy_order 7897 789 a>, <TradeOrder: anc_btc buy_order 7897 789 a>]
so want to process and refine that data, firstly to compare each item to a new order
something like:
if new_order_type=="buy_order":
#crosscheck against sell orders
market_sell_orders = TradeOrder.objects.filter(pair="anc_btc", order_type="sell_order", trade_order_account=price)
#now i need to sort the orders for trade rates above/greater than $new_order_price
#how do i do this?
i now know that this can be accomplished by adding .order_by('trade_order_price')
to the end of the query
if potential_sell_orders is not None:
#trade
do=1
else:
#no sell orders to fill, submit to order book
try:
tradeordersubmit=TradeOrder(pair=order_pair, order_type=order_type, trade_rate=price, trade_amount=quantity, trade_order_account=request.user.username)
tradeordersubmit.save()
order_error=0
except:
order_error="1"
now i need to sort the orders for trade rates above/greater than $new_order_price
You should refine your QuerySet appropriately using QuerySet methods:
market_sell_orders = TradeOrder.objects.filter(pair="anc_btc", order_type="sell_order", trade_order_account=price, trade_rate__gt=<trade_rate>).order_by('-trade_rate')
You can find the tutorial for QuerySet here

Categories