Reputation: 257
I have a Django project with two apps. The first one, market/models.py
, includes a Market class and a Share class, where the latter keeps track of all shares bought or sold on any given market, as follows:
class Market(models.Model):
title = models.CharField(max_length=50, default="")
current_price = models.DecimalField(max_digits=5, decimal_places=2)
description = models.TextField(default="")
shares_yes = models.IntegerField(default=0)
shares_no = models.IntegerField(default=0)
b = models.IntegerField(default=100)
cost_function = models.IntegerField(default=0)
open = models.BooleanField(default=True)
def __str__(self):
return self.title[:50]
def get_absolute_url(self):
return reverse('market_detail', args=[str(self.id)])
class Share(models.Model):
user = models.ForeignKey('users.CustomUser',
on_delete=models.CASCADE,
related_name='user_shares',
default=None)
market = models.ForeignKey(
Market,
on_delete=models.CASCADE,
related_name='market_shares',
default=None)
share = models.IntegerField(default=0)
def __str__(self):
return str(self.share)
def get_absolute_url(self):
return reverse('market_list')
The second app, user/models.py
, is to create custom users, as follows:
class CustomUser(AbstractUser):
points = models.IntegerField(default=1000)
What I want to do is this: on clicking a button on a template for a specific market, the code will loop through all users with shares in that market to add/subtract the value of each share in their possession from their total points (subtraction would happen when users own negative shares, meaning they owe shares on account of short-selling). The value of each share at that point is simply the current market price.
Here is what I have at the moment, in markets/views.py
(the HttpResponseRedirect
at the end simply reloads the page):
def resolve(request, pk):
market = Market.objects.get(pk=pk)
market_users = Share.objects.values('user')
for user in market_users:
target_user = CustomUser.objects.get(username=user)
target_user.points += market.current_price * int(user.share)
market.open = False
market.save()
return HttpResponseRedirect('/' + str(pk))
One problem with this (there might be others) is that target_user ends up being of the form <QuerySet [{'user': 1}, {'user': 1}]>
, which means Django throws the error CustomUser matching query does not exist
.
Any advice would be greatly appreciated!
UPDATE following Higor's suggestion in the comments:
I tried this, which doesn't throw an error, but it fails to update users points:
def resolve(request, pk):
market = Market.objects.get(pk=pk)
market_users = Share.objects.all()
print(market_users) # gives "<QuerySet [<Share: 10>, <Share: 10>]>"
for user in market_users.iterator():
print(user) # gives "10 10"
if user.market == pk:
target_user = CustomUser.objects.get(username=user)
target_user.points += market.current_price * user.share
target_user.save()
market.open = False
market.save()
return HttpResponseRedirect('/' + str(pk))
Upvotes: 1
Views: 98
Reputation: 2046
What you're doing wrong is the way you access your user
inside your Share
object.
from django.shortcuts import get_object_or_404
def resolve(request, pk):
# if no Market with this pk raises a 404
market = get_object_or_404(Market, pk=pk)
# get shares for the specific market
shares = Share.objects.filter(market_id=pk).select_related('user')
print(shares) # gives "<QuerySet [<Share: 10>, <Share: 10>]>"
for share in shares:
target_user = CustomUser.objects.get(pk=share.user.pk)
target_user.points += market.current_price * share.share
target_user.save()
market.open = False
market.save()
return HttpResponseRedirect('/' + str(pk))
Instead of hardcode your URL you can use reverse like here
Upvotes: 1