我想根據用戶輸入過濾模型。例如,用戶想要進行 1-5 天的巡航。在模板中,我有一個帶有這些值的選擇器(1-5、6-9、10-16、17 )。在視圖中,我將這些創建為 kwargs。
def create_kwargs(from_date, nights):
kwargs = {}
got_nights = nights != '-'
got_date = False if not from_date else True
if got_nights and (not got_date):
nights_kwargs(kwargs, nights)
if got_nights and got_date:
nights_kwargs(kwargs, nights)
kwargs['start_months__contains'] = from_date
if (not got_nights) and got_date:
kwargs['start_months__contains'] = from_date
return kwargs
def nights_kwargs(kwargs, nights):
if '-' in nights:
c_min, c_max = nights.split('-')
kwargs['cruise_duration__gte'] = c_min
kwargs['cruise_duration__lte'] = c_max
else:
kwargs['cruise_duration__gte'] = '17'
比我將這些 kwargs 提供給過濾器方法:
for i, area in enumerate(filter_areas):
cruises = GeneralCruise.objects.filter(areas__contains=area, **kwargs)
以前我嘗試檢查相等性并且它有效:
kwargs['cruise_duration'] = '1'
我的問題是,如果我寫 __lte 或 __gte 它會回傳所有模型,即使它們不符合條件。我閱讀了有關此的其他問題,我認為這應該有效。
這是模型:
class GeneralCruise(models.Model):
company = models.CharField(max_length=255, null=True)
ship_name = models.CharField(max_length=255, null=True)
ship_img = models.CharField(max_length=255, null=True)
cruise_name = models.CharField(max_length=255, null=True)
arrival = models.CharField(max_length=255, null=True)
departure = models.CharField(max_length=255, null=True)
cruise_duration = models.CharField(max_length=255, null=True)
start_dates = models.JSONField(default=list)
start_months = models.JSONField(default=list)
cabins = models.JSONField(default=list)
days_desc = models.JSONField(default=list)
port_codes = models.JSONField(default=list)
areas = models.JSONField(default=list)
uj5u.com熱心網友回復:
cruise_durationis a CharField,這意味著它不會按值排序,而是按字典順序排序。例如,按'10' < '9'字典順序排列,因為第一個字符是'1'and '9',并且'1'在字母表中是第一個。
最優雅的解決方案是將其設為數值欄位,例如IntegerField:
class GeneralCruise(models.Model):
# …,
cruise_duration = models.IntegerField(null=True)
# …
這可能會導致遷移出現一些問題,其中可能最有效的擺脫它的方法是洗掉所有遷移,從而重新開始一個新的資料庫。
如果這不是一種選擇,那么將其轉換為 anIntegerField可能是最有效的方法。
在這種情況下,查詢集如下所示:
from django.db.models.functions import Cast, IntegerField
GeneralCruise.objects.annotate(
cruise_duration_int=Cast('cruise_duration', output_field=IntegerField())
)
然后用cruise_duration_int__lte=…和過濾cruise_duration_int__gte=…。但這不是一個優雅的解決方案。
您的模型只有CharFields 和JSONFields也有點奇怪。通常使用ForeignKeys 到其他模型以避免資料重復,并以資料庫范式獲取資料庫。
uj5u.com熱心網友回復:
您遇到的問題是您的cruise_duration領域是一個CharFieldsogte并且lte不表現得如您所愿(例如,如果它是 a IntegerField)。您正在比較字串而不是數值。
為了說明差異:
>>> "9" > "10"
True
>>> 9 > 10
False
您需要將cruise_duration列型別更改為可以根據基數進行比較的欄位型別(如IntegerField)。
因此,當作為__lte/__gte引數提供用于過濾該欄位上的模型時,您的 kwargs 的輸入也需要清理并轉換為整數。
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/365350.html
