4

My url has a keyword "shop_name" variable. There's also the Shop model with "name" field.

In my ListView class I need to make repeating queries to Shop model to get a unicode variable from Shop.get_type() method. Depending on the result, a proper template directory is selected or queryset (Using subclassed django models).

Here's the code.

class OfferList(ListView):
    def get_template_names(self):
        shop = Shop.objects.get(name=self.kwargs['shop_name'])
        return ["shop/%s/offer_list" % shop.get_type()]
    def get_queryset(self):
        shop = Shop.objects.get(name=self.kwargs['shop_name'])
        Offer = shop.get_offers_model()
        return Offer.objects.all()

    def get_context_data(self, **kwargs):
        # again getting shop instance here ...
        shop = Shop.objects.get(name=self.kwargs['shop_name'])
        context = super(OfferList, self).get_context_data(**kwargs)
        context['shop'] = shop
        return context

Question is what is the best way, so I can get some var (shop in this case) available for all methods ? I'm not a python guru (may be the basic problem). I've tried with init overriding but then I couldn't get exchange_name (specified in urls.py) to get the right "shop" instance. I would like to avoid repeating.

Thanks

Robert
  • 365
  • 8
  • 23

1 Answers1

4

Save it in self.shop.

get_queryset is the first method called (see the code for BaseListView's get method). So one solution would be to get your variable there, just as you do in your code, and then also save it to self.shop (just as the BaseListView does with self.object_list).

def get_queryset(self):
    self.shop = Shop.objects.get(name=self.kwargs['shop_name'])
    Offer = self.shop.get_offers_model()
    return Offer.objects.all()

Then in your other methods you can use self.shop:

def get_template_names(self):        
    return ["shop/%s/offer_list" % self.shop.get_type()]
Ofri Raviv
  • 24,375
  • 3
  • 55
  • 55
  • That worked, thanks. I would need the same for any generic view (create, delete) as much of functionality depends on /shop/shop_name/ url variable. Is there a universal method for base view class or should I check for the "first" method being called in every view (get_object() in UpdateView for example?) – Robert Sep 04 '11 at 20:01
  • I think the simplest solution is to override get_queryset or get_object for all of your views. There is a universal View class all class-based-views are derived from (see https://code.djangoproject.com/browser/django/trunk/django/views/generic/base.py) and technically you could put this in there, but then you would have your own View class, and the default CBV don't inherit from it, so you'll end up writing more code, I think. – Ofri Raviv Sep 04 '11 at 22:15
  • this answer defies this programming principle: http://stackoverflow.com/questions/19284857/instance-attribute-attribute-name-defined-outside-init Not to mention that it may no longer work should Django developers change the order in which methods are called. – Saturnix Nov 13 '15 at 19:53
  • Following [this](https://stackoverflow.com/a/36950584/1526703) answer, I put the assignment in get(). Saving the variable as self.* was a great suggestion - thanks! – Anupam Nov 13 '17 at 11:52