如何使用 Q Objects 在 django 模型中查询 float/int 值或字符串?
How can I query for float/int value or string in a django model using Q Objects?
Django 版本=1.8 , IDE=pycharm, python 2.7
我有一个搜索表单,我想根据与产品标题或产品描述或产品价格匹配的字符串在模型中搜索和列出项目 ("products")。
下面是我在 views.py 中的 "searchitems" 部分。我也很困惑下面一行在 get_queryset 函数中做了什么。干杯
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 to define this as it is a default
def get_context_data(self, *args, **kwargs):
context = super(ProductListView, self).get_context_data(*args, **kwargs)
return context
下面是models.py
from django.db import models
from django.core.urlresolvers import reverse
from django.db.models.signals import post_save
from django.utils.text import slugify
# Create your 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 is related to 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 is not None:
return self.sale_price
else:
return self.price
def get_absolute_url(self):
return self.product.get_absolute_url()
# for post save receiver
def product_saved_receiver(sender, instance, created, *args, **kwargs):
# sender=modelclass, instance=actual instance being saved,created=boolean true if record was 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
# you need to install python pillow library to support.
# it checks if file uploaded is actually an image and checks extension
# class ProductImage(models.Model):
# product = models.ForeignKey(Product)
# image = models.ImageField(upload_to='products/') #image will be uploaded to 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 for slugfying
class ProductImage(models.Model):
product = models.ForeignKey(Product)
image = models.ImageField(upload_to=image_upload_to) #image will be uploaded to media/mediaroot/products
def __unicode__(self):
return self.product.title
使用上面的代码,我可以根据价格搜索和列出,例如。 50 或 67.89 但无法搜索字符串并低于错误
http://127.0.0.1:8000/products/?q=eric克莱普顿与王者同行
ValidationError at /products/
[u"'eric clapton riding with the king' value must be a decimal number."]
Request Method: GET
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 with the king' value must be a 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
由于价格需要一个小数值,我们应该提供一个小数值。尝试以下视图:
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 you get a 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)
这用于获取我们视图class ProductListView
的父classes 提供的queryset。在此处查看 python classes 和继承:
http://www.jesshamrick.com/2011/05/18/an-introduction-to-classes-and-inheritance-in-python/
filter_arg |= Q(price=float(query))
这用于附加到我们的 filter_arg 值。与 filter_arg = filter_arg | Q(price=float(query)
相同
float(query)
有了这个,我们试图将查询变量转换为浮点数,我们把它放在 try
语句中,因为它可以给我们一个 ValueError
在这种情况下query
值不是 float
。
Django 版本=1.8 , IDE=pycharm, python 2.7
我有一个搜索表单,我想根据与产品标题或产品描述或产品价格匹配的字符串在模型中搜索和列出项目 ("products")。
下面是我在 views.py 中的 "searchitems" 部分。我也很困惑下面一行在 get_queryset 函数中做了什么。干杯
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 to define this as it is a default
def get_context_data(self, *args, **kwargs):
context = super(ProductListView, self).get_context_data(*args, **kwargs)
return context
下面是models.py
from django.db import models
from django.core.urlresolvers import reverse
from django.db.models.signals import post_save
from django.utils.text import slugify
# Create your 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 is related to 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 is not None:
return self.sale_price
else:
return self.price
def get_absolute_url(self):
return self.product.get_absolute_url()
# for post save receiver
def product_saved_receiver(sender, instance, created, *args, **kwargs):
# sender=modelclass, instance=actual instance being saved,created=boolean true if record was 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
# you need to install python pillow library to support.
# it checks if file uploaded is actually an image and checks extension
# class ProductImage(models.Model):
# product = models.ForeignKey(Product)
# image = models.ImageField(upload_to='products/') #image will be uploaded to 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 for slugfying
class ProductImage(models.Model):
product = models.ForeignKey(Product)
image = models.ImageField(upload_to=image_upload_to) #image will be uploaded to media/mediaroot/products
def __unicode__(self):
return self.product.title
使用上面的代码,我可以根据价格搜索和列出,例如。 50 或 67.89 但无法搜索字符串并低于错误
http://127.0.0.1:8000/products/?q=eric克莱普顿与王者同行
ValidationError at /products/
[u"'eric clapton riding with the king' value must be a decimal number."]
Request Method: GET
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 with the king' value must be a 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
由于价格需要一个小数值,我们应该提供一个小数值。尝试以下视图:
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 you get a 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)
这用于获取我们视图class ProductListView
的父classes 提供的queryset。在此处查看 python classes 和继承:
http://www.jesshamrick.com/2011/05/18/an-introduction-to-classes-and-inheritance-in-python/
filter_arg |= Q(price=float(query))
这用于附加到我们的 filter_arg 值。与 filter_arg = filter_arg | Q(price=float(query)
float(query)
有了这个,我们试图将查询变量转换为浮点数,我们把它放在 try
语句中,因为它可以给我们一个 ValueError
在这种情况下query
值不是 float
。