Обновление Django вместо вставки новой записи - PullRequest
1 голос
/ 28 февраля 2012

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

Кроме того, когда 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))

Ответы [ 2 ]

6 голосов
/ 28 февраля 2012

Посмотрите на эту строку:

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 голосов
/ 28 февраля 2012

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

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

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

...