简体   繁体   中英

DJANGO:How to perform AND operation for my query?

There are two models .I want to make query to extract only the app exact app related Adspaces .

models.py

class Appname(models.Model):
     user=models.ForeignKey(User,related_name='appname', null=True, default=None,on_delete=models.CASCADE)  
     name=models.CharField(max_length=150,blank=False,null=False,help_text='Add your new App') 
     def __str__(self):
         return self.name
     def get_absolute_url(self):
         return reverse("dashapp:space",kwargs={'pk':self.pk})


class Adspace(models.Model):
     user=models.ForeignKey(User,related_name='adspace', null=True, default=None,on_delete=models.CASCADE)  
     ad_space=models.CharField(max_length=150,blank=False,null=False) 
     app=models.ForeignKey('Appname', related_name='appnames',default=None, on_delete=models.CASCADE)

     PID_TYPE = (
    ('FN','FORMAT_NATIVE'),
    ('FNB','FORMAT_NATIVE_BANNER'),
    ('FI','FORMAT_INTERSTITIAL'),
    ('FB','FORMAT_BANNER'),
    ('FMR','FORMAT_MEDIUM,RECT'),
    ('FRV','FORMAT_REWARDED_VIDEO'),
)
    format_type=models.CharField(max_length=3,choices=PID_TYPE,default='FN',blank=False, null=False)

    def __str__(self):
         return self.ad_space
    def get_absolute_url(self):
         return reverse("dashapp:create",kwargs={'pk':self.pk})

Views.py

SHowing the one where i need to the query

      class spacelist(LoginRequiredMixin,ListView):
              model=Adspace
              template_name='adspace_list.html'
              def get_queryset(self):
                       query_set=super().get_queryset()
                       return query_set.filter(user=self.request.user)

Here I need to perform One more query so that EACH APP show their own adspaces when clicked right now every app show every show adspaces. I have the idea what to do as if i compare app_id then it'll show the exact app related adspaces, but i dont know how to write query for the same as i already have one query present.???

You chain another filter at the end like this:

class spacelist(LoginRequiredMixin,ListView):
    model=Adspace
    template_name='adspace_list.html'

    def get_queryset(self):
        query_set = super().get_queryset()
        query_set = query_set.filter(user=self.request.user)
        app_id = [...]
        return query_set.filter(app_id=app_id)

The problem left is to find out what is the app_id coming from. How do you know what is the current app? Several options here.

Option 1: From the request

It can come from the current user: self.request.user.appname.all() but that will give you multiple apps, if the user can only have one app, you should change your model Appname.user to a OneToOneField .

Otherwise, I suggest changing your related_name='appnames' to reflect the multiplicity in the reverse relationship.

Option 2: From the URL

It can come from the URL, your space list view should extract an app_id parameter from the URL where it's defined:

url(r'^(?P<app_id>[0-9]+)/spaces/$', spacelist.as_view(), name='space_list'),

And then in the spacelist view, you would get this parameter like this:

app_id = self.kwargs['app_id']
return query_set.filter(app_id=app_id)

Hope that helps

UPDATE:

Also worth noting that QuerySets are lazy , meaning the result will get evaluated as late as possible by Django. Therefore, when you call:

query_set = query_set.filter(user=self.request.user)

The Django ORM doesn't execute any DB queries yet, and you can chain more filters after that:

query_set = query_set.filter(user=self.request.user)
query_set = query_set.filter(app_id=app_id)

Which behind the scenes is extending the query that will be executed when required. But at this point, no query is actually run. To see the query that will get executed you can print out the query attribute of the QuerySet:

print(query_set.query)

Which should log something like:

SELECT "app_adspace"."user_id" ... 
FROM 
  "app_adspace" 
WHERE 
  "app_adspace"."user_id" = 1234 AND "app_adspace"."app_id" = 5678 

You could try using a Q objects: https://docs.djangoproject.com/en/2.1/topics/db/queries/#complex-lookups-with-q-objects

From what I understand you are trying to filter both on the app_id and the request user at the same time, so you could try look something like this:

from django.db.models import Q

...
def get_queryset(self):
    query_set=super().get_queryset()
    return query_set.filter(Q(user=self.request.user) & Q(app_id=app_id))
...

This lets you do a single filter with both your requirements at the same time (ie retrieve the Adspace instances for a specific user with a specific Appname ).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM