2015-08-18 2 views
1

У меня есть таблица форм того же класса, которая содержит ModelChoiceField. И каждая форма в одной строке имеет тот же набор запросов для этого поля. Проблема в том, что каждый раз, когда форма отображается, это новый запрос, который увеличивает невыносимо количество запросов.Django multiple forms with modelchoicefield -> слишком много запросов

Единственное решение, с которым я столкнулся, состоит в том, чтобы построить форму на ходу с помощью js вместо того, чтобы позволить django отображать ее самостоятельно. Есть ли способ кэшировать эти запросы или несколько предварительно загрузить его сразу?

views.py: 
shift_table=[] 
for project in calendar_projects: 
    shift_table.append([]) 
    project_branches = project.branches.all() 
    for i, week in enumerate(month): 
     for day in week: 
      shift_table[-1].append(
       CreateShiftCalendarForm(initial={'date': day}, branch_choices=project_branches)) 


forms.py: 
CreateShiftCalendarForm(EditShiftCalendarForm): 

    class Meta(ShiftForm.Meta): 
     fields = ('project_branch', 'date') + ShiftForm.Meta.fields 
     widgets = {'date': forms.HiddenInput(), 'length': forms.NumberInput(attrs={'step': 'any'}), 'project_branch': forms.Select()} 

    def __init__(self, *args, **kwargs): 
     branch_choices = kwargs.pop('branch_choices', ProjectBranch.objects.none()) 
     super(CreateShiftCalendarForm, self).__init__(*args, **kwargs) 

     self.fields['project_branch'].queryset = branch_choices 
     self.fields['project_branch'].empty_label = None 
+0

Можете ли вы предоставить свой код формы? – GwynBleidD

+0

Там вы идете @GwynBleidD – Dalbenn

ответ

1

Я подклассифицировал ChoiceField как предложено GwynBleidD, и он работает достаточно на данный момент.

class ListModelChoiceField(forms.ChoiceField): 
    """ 
    special field using list instead of queryset as choices 
    """ 
    def __init__(self, model, *args, **kwargs): 
     self.model = model 
     super(ListModelChoiceField, self).__init__(*args, **kwargs) 

    def to_python(self, value): 

     if value in self.empty_values: 
      return None 
     try: 
      value = self.model.objects.get(id=value) 
     except self.model.DoesNotExist: 
      raise ValidationError(self.error_messages['invalid_choice'], code='invalid_choice') 
     return value 


    def valid_value(self, value): 
     "Check to see if the provided value is a valid choice" 

     if any(value.id == int(choice[0]) for choice in self.choices): 
      return True 
     return False 
2

ModelChoiceField является подклассом ChoiceField, в которой «нормальные» выборы заменяются итератора, который будет перебирать при условии QuerySet. Также существует настраиваемый метод to_python, который будет возвращать фактический объект, а не pk. К сожалению, этот итератор сбрасывает запрос и удаляет базу данных еще раз для каждого поля выбора, даже если они разделяют запрос

Что вам нужно сделать, это подкласс ChoiceField и имитирующее поведение ModelChoiceField с одним отличием: вместо этого он будет принимать статический список выбора запроса. Этот список выбора вы будете строить в своем представлении один раз для всех полей (или форм).