4

我正在尝试使用显示相关实体的组合来呈现表单。因此,我使用的是 ModelChoiceField。

这种方法效果很好,直到我需要限制要显示的实体。如果我使用简单的查询表达式,它也可以很好地工作,但是如果我使用原始 SQL 查询,事情就会中断。

所以我的代码有效,将查询集设置为过滤器表达式。

class ReservationForm(forms.Form):
    location_time_slot = ModelChoiceField(queryset=LocationTimeSlot.objects.all(), empty_label="Select your prefered time")

def __init__(self,*args,**kwargs):
    city_id = kwargs.pop("city_id")     # client is the parameter passed from views.py
    super(ReservationForm, self).__init__(*args,**kwargs)

    # TODO: move this to a manager        
    self.fields['location_time_slot'].queryset = LocationTimeSlot.objects.filter(city__id = city_id )

但是,如果我将其更改为原始查询,我就会开始遇到问题。不起作用的代码:

class ReservationForm(forms.Form):
        location_time_slot = ModelChoiceField(queryset=LocationTimeSlot.objects.all(), empty_label="Select your prefered time")

    def __init__(self,*args,**kwargs):
        city_id = kwargs.pop("city_id")     # client is the parameter passed from views.py
        super(ReservationForm, self).__init__(*args,**kwargs)

        # TODO: move this to a manager        
        query = """SELECT ts.id, ts.datetime_to, ts.datetime_from, ts.available_reserves, l.name, l.'order' 
    FROM  reservations_locationtimeslot AS ts
     INNER JOIN reservations_location AS l ON l.id = ts.location_id 
     WHERE l.city_id = %s     
     AND ts.available_reserves > 0  
     AND ts.datetime_from > datetime() """

    time_slots = LocationTimeSlot.objects.raw(query, [city_id])

    self.fields['location_time_slot'].queryset = time_slots

尝试呈现小部件时遇到的第一个错误是:'RawQuerySet' 对象没有属性'all'

多亏了在此处输入链接描述中的一项评论,我可以解决这个问题,方法是:

 time_slots.all = time_slots.__iter__ # Dummy fix to allow default form rendering with raw SQL

但是现在我在发布表单时得到了类似的东西:'RawQuerySet'对象没有属性'get'

是否有适当的方法来准备供 ModelChoiceField 使用的 RawQuerySet?

谢谢!

4

2 回答 2

1

你确定你真的需要一个原始查询吗?只看那个查询,我看不出有任何理由你不能用filter(location__city=city_id, available_reserves__gte=0, datetime_from__gt=datetime.datetime.now()).

原始查询集缺少在传统查询集上定义的许多方法,因此如果不为所有这些方法编写自己的定义,将它们放在适当的位置是不可能的。

于 2013-06-26T22:40:35.247 回答
1

我暂时修复了添加缺失方法的问题。我目前使用 ModelChoiceField 的方式只需要添加 all() 和 get() 方法,但在不同的场景中,您可能还需要添加一些其他方法。这也不是一个完美的解决方案,因为:1)以这种方式定义 get 方法可能会产生不正确的结果。我认为 get() 方法用于验证所选选项是否在 all() 返回的选项内。我临时实现它的方式只是验证表中是否存在id。2)我猜get方法以这种方式指定的性能较低。

如果有人能想到更好的解决方案,请告诉我。

所以我的临时解决方案:

class LocationTimeSlotManager(models.Manager):
    def availableSlots(self, city_id):
        query = """SELECT ts.id, ts.datetime_to, ts.datetime_from, ts.available_reserves, l.name, l.'order' 
            FROM  reservations_locationtimeslot AS ts
            ..... 
            ..... 
            MORE SQL """ 

        time_slots = LocationTimeSlot.objects.raw(query, [city_id])

        # Dummy fix to allow default form rendering with raw SQL
        time_slots.all = time_slots.__iter__ 
        time_slots.get = LocationTimeSlot.objects.get

        return time_slots
于 2013-07-01T20:31:21.270 回答