Django модель формы со связанными объектами, как сохранить и редактировать - PullRequest
0 голосов
/ 23 января 2020

Я разрабатываю приложение, у которого есть связанные модели, такие как Trip, могут иметь несколько загрузок.

Итак, как мне создать форму создания для достижения желаемой функциональности? Я знаю, что набор форм можно использовать для достижения функциональности, но я хочу, чтобы пользовательские функции, такие как:

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

Я реализовал эту функциональность двумя способами, но я ищу более аккуратный и понятный подход. До сих пор я делал:

  1. Я добавил нагрузки, используя ajax, и извлек идентификатор сохраненного груза и сохранил его в скрытом поле, при отправке формы главной поездки я создаю объект для отключения и извлечения объекта Loads с использованием идентификатора и сопоставления этого идентификатора отключения с объектом загрузки.

  2. Я сохраняю данные о нагрузках в объектах javascript и позволяю пользователю выполнять добавление, редактирование, удаление грузов, не заходя в базу данных, как только пользователь отправит основную форму поездки, я опубликую данные о нагрузках и создавать объекты и сохранять в базе данных.

Пожалуйста, дайте мне знать, если кто-то выполнил этот тип работы и придерживается более чистого подхода

Ответы [ 2 ]

0 голосов
/ 23 января 2020

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

Вот схема с реструктурированным представлением, которую я использую для обработки нескольких форм (не редактировал имена, указанные в приложении c, не хочу вводить ошибки):

def receive_uncoated( request): #Function based view

    # let's put form instantiation in one place not two, and reverse the usual test. This
    # makes for a much nicer layout with actions not sandwiched by "boilerplate" 
    # note any([ ]) forces invocation of both .is_valid() methods 
    # so errors in second form get shown even in presence of errors in first

    args = [request.POST, ] if request.method == "POST" else []
    batchform = CreateUncWaferBatchForm( *args )
    po_form =  CreateUncWaferPOForm(     *args, prefix='po')
    if request.method != "POST" or any(  
        [ not batchform.is_valid(), not po_form.is_valid() ]):

        return render(request, 'wafers/receive_uncoated.html',   # can get this out of the way at the top
            {'batchform': batchform,  
            'po_form': po_form, 
        })

    #POST, everything is valid, do the work

    # create and save some objects based on the validated forms ... 

    return redirect( 'wafers:ok' )   

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

Вернемся к этому вопросу: вы бы заменили batch_form на trip_form и po_form с ModelFormset для загрузки. После проверки формы и набора форм вы создадите все запрошенные объекты, используя

    trip = trip_form.save( commit=False)
    load_list = loads_formset.save( commit = False)

    # fill in some related object in trip then save trip
    foo = Foo.objects.get( ...)
    trip.foo = foo
    trip.save() 

    # link loads to trip and save them
    for load in load_list:
        load.trip = trip
        load.save()

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

0 голосов
/ 23 января 2020

Звучит как хороший пример использования django-extra-views.

(установите с pip install django-extra-views и добавьте extra_views к вашему INSTALLED_APPS)

Вы можете создавать и обновлять модели со строками с простыми представлениями на основе классов.

В представлениях

from extra_views import CreateWithInlinesView, UpdateWithInlinesView, InlineFormSetFactory

from .models import Load, Trip

class LoadInline(InlineFormsetFactory):
    model = Load
    fields = [<add your field names here>]


class CreateTripView(CreateWithInlinesView):
    model = Trip
    inlines = [LoadInline]
    fields = [<add your trip model fields here>]
    template = 'trips/create.html`

template:

<form method="post">
  ...
  {{ form }}

  {% for formset in inlines %}
    {{ formset }}
  {% endfor %}
  ...
  <input type="submit" value="Submit" />
</form>

Представление обновления очень похоже. Вот документы: https://github.com/AndrewIngram/django-extra-views#createwithinlinesview -или-обновление с интерактивным обзором

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...