Django: обновление модели с текущим пользователем при изменении немодельного поля формы

Я создаю страницу, которая позволяет пользователям редактировать записи задач и связанных с ними активностей (у одной задачи может быть много активностей), все на одной странице. Я хочу позволить пользователю "принять" один или несколько видов деятельности, отметив соответствующее поле, и связать его пользовательскую запись с каждым видом деятельности через ForeignKey. Вот выдержки из моего кода...

models.py

from django.contrib.auth.models import User

class Task(models.Model):
    category    = models.CharField(max_length=300)
    description = models.CharField(max_length=300)

class Activity(models.Model):
    task  = models.ForeignKey(Task, on_delete=models.CASCADE)
    title = models.CharField(max_length=150)
    notes = models.TextField(blank=True)
    owner = models.ForeignKey(User, on_delete=models.SET_NULL, null=True, blank=True)

Активность "владелец" связана с User из стандартной модели пользователя Django.

Я добавил дополнительное поле в определение формы для поля adopt - я не хочу добавлять его в модель, поскольку мне не нужно сохранять его после того, как оно выполнит свою работу.

forms.py

class ActivityForm(forms.ModelForm):
    adopt = forms.BooleanField(required=False)

    class Meta:
        model = Activity
        fields = '__all__'

views.py

def manage_task(request, pk):
    task = Task.objects.get(pk = pk)
    TaskInlineFormSet = inlineformset_factory(Task, Activity, 
        form = ActivityForm)
    if request.method == "POST":
        form = TaskForm(request.POST, instance = task)
        formset = TaskInlineFormSet(request.POST, instance = task)
        if form.has_changed() and form.is_valid():
            form.save()
        if formset.has_changed() and formset.is_valid():
            ## ? DO SOMETHING HERE ? ##
            formset.save()
        return redirect('manage_task',pk=task.id)
    else:
        form = TaskForm(instance = task)
        formset = TaskInlineFormSet(instance = task)
    context = {'task': task, 'task_form': form, 'formset': formset}
    return render(request, 'tasks/manage_task.html', context)

Когда поле adopt отмечено на форме, я хочу иметь возможность установить поле owner в этой форме на текущего пользователя до того, как связанный экземпляр модели будет обновлен и сохранен.

Я просто не могу понять, как это сделать - если бы это была одна форма (а не InlineFormSet), я думаю, я мог бы поместить код в представление, чтобы изменить значение владельца в поле формы перед сохранением (я не пробовал этого). Или попробовать save(commit = False) и обновить экземпляр модели, а затем save() его. Может быть, мне нужно итеративно перебрать набор форм в коде представления и попробовать один из этих вариантов, когда я найду тот, у которого adopt=True?

When the adopt field is ticked on the form, I want to be able to set the owner field in that form to the current user before the associated model instance is updated and saved.

formset = TaskInlineFormSet(request.POST, instance = task)
if formset.adopt:
    # If True
    formset.user = request.user
    formset.save()

I think I could put code in the view to change the owner value in the form field before it was saved (I haven't tried this). Вам стоит попробовать.

Я не доволен этим решением, но оно работает. Я перебираю формы и изменяю экземпляр объекта, если мое поле adopt установлено.

views.py

def manage_task(request, pk):
    task = Task.objects.get(pk = pk)
    TaskInlineFormSet = inlineformset_factory(Task, Activity, 
        form = ActivityForm)
    if request.method == "POST":
        form = TaskForm(request.POST, instance = task)
        formset = TaskInlineFormSet(request.POST, instance = task)
        if form.has_changed() and form.is_valid():
            form.save()
        if formset.has_changed() and formset.is_valid():

            ## HERE'S WHAT I ADDED ##
            for form in formset:
                if form.cleaned_data['adopt'] is True:
                    form.instance.owner = request.user
            ## END OF ADDITIONS ##

            formset.save()
        ## return redirect('manage_task',pk=task.id) # CHANGED THIS BECAUSE I WASN'T RETURNG ERRORS!
        if not form.errors and not formset.total_error_count():
            return redirect('manage_task',pk=task.id)
    else:
        form = TaskForm(instance = task)
        formset = TaskInlineFormSet(instance = task)
    context = {'task': task, 'task_form': form, 'formset': formset}
    return render(request, 'tasks/manage_task.html', context)

Хотелось бы найти в документации больше информации о том, как работает сохранение формы, но, думаю, мне придется заглянуть в код, если мне нужно больше деталей.

Вернуться на верх