Ad

Accessing Two Apps In One View In Django

- 1 answer

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))
Ad

Answer

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

Ad
source: stackoverflow.com
Ad