n_ck
n_ck

Reputation: 45

Django display data for current user only

I'm looking to show the data of the Performance model for the current user only. Right now the page shows all performance data, not only the data of the logged in user.

I'm not sure if I have the models.py setup incorrectly (does every model need to have a foreignkey related to the user?) or if there is a solution for this in the views.py file (I tried this using get_context_data but couldn't get it to work)

Any help is much appreciated!

models.py

class Adaccount(models.Model):
    accountname = models.CharField(max_length=250)

    def __str__(self):
        return self.accountname

class Performance(models.Model):
    adaccount = models.ForeignKey(Adaccount, on_delete=models.CASCADE)
    date = models.DateField(auto_now_add=True)
    campaign = models.CharField(max_length=500)
    adset = models.CharField(max_length=500)
    clicks = models.IntegerField()
    impressions = models.IntegerField()
    ctr = models.FloatField()
    cpc = models.FloatField()
    cpm = models.FloatField()
    conv1 = models.IntegerField()
    conv2 = models.IntegerField(blank=True, null=True)
    conv3 = models.IntegerField(blank=True, null=True)

    def __str__(self):
        return str(self.date) + ' - ' + str(self.adaccount)


class Account(models.Model):
    user = models.OneToOneField(User, on_delete=models.CASCADE)
    adaccounts = models.ForeignKey(Adaccount,null=True)
    company = models.CharField(max_length=250, blank=True)
    website = models.CharField(max_length=30, blank=True)

    def __str__(self):
        return self.company

views.py

class IndexView(LoginRequiredMixin, generic.ListView): 
    model = Performance
    context_object_name = 'all_performance'
    template_name = 'dashboard/index.html'
    login_url = '/login/'
    redirect_field_name = 'redirect_to'

    def get_queryset(self):
        return Performance.objects.all()


class HomeView(TemplateView):
    model = Adaccount
    template_name = 'dashboard/home.html'

HTML Template

<strong>CTR | CPC | CPM</strong><br>

{% for daily in all_performance %}
<span>{{ daily.ctr }} | {{ daily.cpc }} | {{ daily.cpm }}</span><br>        
{% endfor %}

Upvotes: 0

Views: 7828

Answers (1)

John Suh
John Suh

Reputation: 110

The key problem seems to be with the

    def get_queryset(self):
        return Performance.objects.all()

part.

You are getting all the Performance objects in the view(as you can see from objects.all() part of the code).

You have to somehow filter the Performance with the user. You can get the current user with self.request.user in the view.

Problem is, looking at your model, user seems to be on a related related model ( Performance -> Adaccount -> Account) which makes the operation you desire a bit complicated. This is fine as long as this is the model structure you intended to create, which gets into the architecture of your Database.

Assuming that you will not change the architecture, this is what has to happen with plain English:

Filter all the Accounts with the request.user. From those Accounts, get all the Adaccounts. Filter all the Performances from the Adaccounts.

    def get_queryset(self):
        user = self.request.user
        adaccount_list = Account.objects.filter(user=user)\
                         .values_list('adaccounts', flat=True)
        return Performance.objects.filter(adaccount__in=adaccount_list)

This is one approach, albeit not the most efficient but easy to visualize. Others may find better approaches - do let me know if there is any problem!

Upvotes: 2

Related Questions