2012-02-27 5 views
1

У меня странная проблема с Django 1.3. Когда я пытаюсь добавить новое действие с помощью ActivityForm, активность часто обновляется, даже если я явно создаю новый объект Activity, а не Id.Обновление Django вместо вставки новой записи

Кроме того, когда init моего класса ActivityForm имеет явный параметр trip_id, пользовательский интерфейс отображает «Выберите правильный вариант. Этот выбор не является одним из доступных вариантов». для местоположения поля (хотя выбранный выбор действителен). Однако, если я сделаю это необязательным параметром, и я вытащил его из kwargs, я не вижу этой проблемы.

Может кто-нибудь, пожалуйста, взгляните на код ниже и посмотрите, что я делаю неправильно?

forms.py

class DestinationMultipleChoiceField(ModelMultipleChoiceField): 
    def label_from_instance(self, obj): 
     return obj.city_name 

class ActivityForm(forms.Form): 
    description = forms.CharField(max_length=100, required=True) 
    location = DestinationChoiceField(queryset = Visit.objects.none(), empty_label=None, required=True) 

    def __init__(self, trip_id = None, *args, **kwargs): 
     super(ActivityForm, self).__init__(*args, **kwargs) 
     if trip_id is not None: 
      self.fields['location'].queryset = Visit.objects.filter(trip=trip_id).all().select_related('destination') 

    # A new Activity() is created if nothing is provided 
    def save(self, activity = Activity()): 
     if not self.is_valid(): 
      raise forms.ValidationError('ActivityForm was not validated first before trying to call save().') 

     activity.visit = self.cleaned_data['location'] 
     activity.description = self.cleaned_data['description'] 
     activity.added_by = User.objects.get(pk=1) 
     activity.save() 

views.py

def add_activity(request, trip_id = None, template_name = 'edit-form.html'): 
    if request.POST: 
     form = ActivityForm(trip_id, request.POST) 
     if form.is_valid(): 
      form.save() 
      return HttpResponseRedirect(reverse('views.list_trip')) 
    else: 
     form = ActivityForm(trip_id) 

    return render_to_response(template_name, { 
     'page_title': 'Add', 
     'form': form, 
    }, context_instance=RequestContext(request)) 

ответ

6

Посмотрите на этой линии:

def save(self, activity = Activity()): 

В Python, параметры по умолчанию вычисляются один раз; таким образом, когда метод save называется в первый раз, будет создан новый Activity, но последующие вызовы будут использовать , чтоActivity.

Изменить save на что-то вроде этого:

def save(self, activity=None): 
    if activity is None: 
     activity = Activity() 
    # Rest of the method 

Затем, новый Activity будет создана при каждом вызове (если один не поставляется в качестве аргумента).

2

экземпляры модели изменчивы. Поэтому они должны никогда не использовать как аргументы по умолчанию для метода, как в save. Есть причина, почему вы никогда не видели этого ни в одной документации или примерах.

Как отмечалось в очень многих других вопросах на этом сайте, аргументы по умолчанию оцениваются по определению, а не по исполнению. Таким образом, каждый вызов save без аргумента активности будет использовать тот же самый Мероприятие, которое изначально было определено.

Однако я не понимаю, почему вы не используете ModelForm, который в большинстве случаев делает это для вас.

+0

Я не использую ModelForm, потому что мне нужно касаться нескольких объектов. – Martin

Смежные вопросы