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

У меня есть набор связанных моделей в приложении Django 1.5: Events, у которых есть EventSessions, и EventSessionRegistrations, которые принадлежат EventSessions.

Я изо всех сил пытаюсь создать общее представление на основе классов для регистрационной формы, ориентированной на пользователя, где пользователь регистрируется для участия в EventSession. В частности, проблема заключается в исключении поля, для которого EventSession предназначена регистрация, из отображения в форме, но при этом устанавливается это значение на основе контекста и/или URL-адреса.

Сначала я попытаюсь объяснить на примере использования:

  1. Пользователь переходит к '/events/foo/bar', где foo — это Event, а bar — это EventSession.
  2. По этому URL есть ссылка для регистрации на EventSession, ведущая к '/events/foo/bar/register/'. Отображается форма для модели EventSessionRegistration, но без выбора EventSession в пользовательском интерфейсе, поскольку эта информация уже «установлена» URL-адресом.
  3. После успешной отправки формы пользователь перенаправляется на статическую страницу «Спасибо».

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

from django.views.generic.edit import CreateView

class RegistrationCreate(CreateView):
    form_class = SessionRegistrationForm
    success_url = '/thanks/'
    template_name = 'events/registration_create.html'

    def get_context_data(self, *args, **kwargs):
        """Set the context of which Event, and which EventSession.
           Return 404 if either Event or EventSession is not public."""
        context = super(RegistrationCreate, self).get_context_data(**kwargs)
        s = get_object_or_404(
            EventSession,
            event__slug=self.kwargs['event_slug'],
            event__is_public=True,
            slug=self.kwargs['session_slug'],
            is_public=True)
        context['session'] = s
        context['event'] = s.event
        return context

Шаблон URL для этого представления (включен из базы urls.py):

url(r'^(?P<event_slug>[\w-]+)/(?P<session_slug>[\w-]+)/register/$',
    RegistrationCreate.as_view(), name="event_session_registration"),

В ModelForm я попытался преобразовать поле ForeignKey session в поле EventSessionRegistration (указывающее на EventSession), чтобы показать виджет HiddenInput():

class SessionRegistrationForm(forms.ModelForm):

    class Meta:
        model = EventSessionRegistration
        widgets = {
            'session': HiddenInput()
        }

Но я до сих пор не знаю, как установить начальное значение этого поля в идентификатор значения 'session', которое я установил в get_context_data. Я пытался установить self.initial = {'session': s.id} внутри get_context_data, но я предполагаю, что атрибут initial уже используется для построения формы в этот момент.

Любые идеи о наилучшем способе достижения этого? Что мне не хватает?


person Emil    schedule 28.06.2013    source источник
comment
Но если вы получаете EventSession из базы данных, она должна уже иметь id, чтобы вы могли сделать это в своем шаблоне session.id.   -  person Henrik Andersson    schedule 28.06.2013
comment
@limelights Да, я играл с этим, создавая скрытый <input> и добавляя к нему session.id, но затем мне пришлось исключить поле session из формы, из-за чего Django все равно игнорировал это поле при публикации формы. ...   -  person Emil    schedule 28.06.2013
comment
А, теперь понял :)   -  person Henrik Andersson    schedule 28.06.2013


Ответы (1)


Правильно, я нашел этот вопрос, который касается той же проблемы. В итоге я получил следующую переопределенную пост-функцию в представлении и вручную вывел идентификатор сеанса в шаблоне в скрытом поле:

def post(self, request, *args, **kwargs):
    self.object = None
    evt_session = get_object_or_404(
        EventSession, pk=int(self.request.POST['session']))
    form_class = self.get_form_class()
    form = self.get_form(form_class)

    form.instance.session = evt_session

    if form.is_valid():
        return self.form_valid(form)
    else:
        return self.form_invalid(form)

Кроме того, я нашел ccbv.co.uk, который является отличным ресурсом для получения сведений обо всех методах и атрибутах в CBV:s, который дает рекомендации относительно того, как следует структурировать переопределение.

person Emil    schedule 28.06.2013