python - How can I query for float/int value or string in a django model using Q Objects? -
django version=1.8 , ide=pycharm, python 2.7
i have search form , want search , list items("products") in model based on string matching product title or product description or product price.
below "searchitems" part inside views.py . im confused line below in get_queryset function. cheers
qs = super(productlistview, self).get_queryset(*args,**kwargs)
#
# search inside model function def get_queryset(self, *args, **kwargs): qs = super(productlistview, self).get_queryset(*args,**kwargs) query = self.request.get.get("q") if query: qs = self.model.objects.filter( q(title__icontains=query) | q(description__icontains=query) | q(price=query) ) return qs class productlistview(listview): model = product queryset=product.objects.all() #no need define default def get_context_data(self, *args, **kwargs): context = super(productlistview, self).get_context_data(*args, **kwargs) return context
below models.py
django.db import models django.core.urlresolvers import reverse django.db.models.signals import post_save django.utils.text import slugify # create models here. class productqueryset(models.query.queryset): def active(self): return self.filter(active=true) class productmanager(models.manager): def get_queryset(self): return productqueryset(self.model, using=self.db) def all(self, *args, **kwargs): return self.get_queryset().active() class product(models.model): title = models.charfield(max_length=120) description = models.textfield(blank=true, null=true) price = models.decimalfield(decimal_places=2, max_digits=10) active = models.booleanfield(default=true) objects = productmanager() def __unicode__(self): return self.title def get_absolute_url(self): return reverse("product_detail", kwargs={"pk": self.pk}) # or use this- return "/product/%s"%(self.pk) class variation(models.model): product = models.foreignkey(product) ##this means each variation related single product title = models.charfield(max_length=120) price = models.decimalfield(decimal_places=2, max_digits=10) sale_price = models.decimalfield(decimal_places=2, max_digits=10, null=true, blank=true) active = models.booleanfield(default=true) inventory = models.integerfield(null=true, blank=true) # default=-1 means unlimited def __unicode__(self): return self.title def get_price(self): if self.sale_price not none: return self.sale_price else: return self.price def get_absolute_url(self): return self.product.get_absolute_url() # post save receiver def product_saved_receiver(sender, instance, created, *args, **kwargs): # sender=modelclass, instance=actual instance being saved,created=boolean true if record created product = instance variations = product.variation_set.all() if variations.count() == 0: new_var = variation() new_var.product = product new_var.title = "default" new_var.price = product.price new_var.save() post_save.connect(product_saved_receiver, sender=product) # product image # need install python pillow library support. # checks if file uploaded image , checks extension # class productimage(models.model): # product = models.foreignkey(product) # image = models.imagefield(upload_to='products/') #image uploaded media/mediaroot/products # # def __unicode__(self): # return self.product.title #slugify def image_upload_to(instance, filename): title = instance.product.title slug = slugify(title) file_extension = filename.split(".")[1] # or basename,file_extension = filename.split(".") new_filename = "%s.%s" %(instance.id,file_extension) return "products/%s/%s" %(slug, filename) # above function changed slugfying class productimage(models.model): product = models.foreignkey(product) image = models.imagefield(upload_to=image_upload_to) #image uploaded media/mediaroot/products def __unicode__(self): return self.product.title
with above codes can search , list according price eg. 50 or 67.89 cannot search strings , below error
http://127.0.0.1:8000/products/?q=eric clapton riding king
validationerror @ /products/ [u"'eric clapton riding king' value must decimal number."] request method: request url: http://127.0.0.1:8000/products/?q=eric%20clapton%20riding%20with%20the%20king django version: 1.8.4 exception type: validationerror exception value: [u"'eric clapton riding king' value must decimal number."] exception location: c:\anaconda\lib\site-packages\django\db\models\fields\__init__.py in to_python, line 1602 python executable: c:\anaconda\python.exe python version: 2.7.10
since price requires decimal value should supply decimal value. try following view:
def get_queryset(self, *args, **kwargs): qs = super(productlistview, self).get_queryset(*args,**kwargs) query = self.request.get.get("q", false) # provide default value or keyerror if query: filter_arg = q(title__icontains=query) | q(description__icontains=query) try: filter_arg |= q(price=float(query)) except valueerror: pass qs = self.model.objects.filter(filter_arg) return qs
qs = super(productlistview, self).get_queryset(*args,**kwargs)
used obtain queryset provided parent classes of our view class productlistview
. in python classes , inheritance here: http://www.jesshamrick.com/2011/05/18/an-introduction-to-classes-and-inheritance-in-python/
filter_arg |= q(price=float(query))
used append our filter_arg value. it's same filter_arg = filter_arg | q(price=float(query)
float(query)
trying convert query variable float , put in try
statement because give valueerror
in case query
value not float
.
Comments
Post a Comment