# changing state and metadata and commenting on Internet Drafts for # Area Directors and Secretariat import re, os from datetime import datetime, date, time, timedelta from django.http import HttpResponse, HttpResponseRedirect, Http404 from django.shortcuts import render_to_response, get_object_or_404 from django.core.urlresolvers import reverse as urlreverse from django.template.loader import render_to_string from django.template import RequestContext from django import forms from django.utils.html import strip_tags from django.db.models import Max from django.conf import settings from ietf.utils.mail import send_mail_text from ietf.ietfauth.decorators import group_required from ietf.idtracker.templatetags.ietf_filters import in_group from ietf.ietfauth.decorators import has_role from ietf.idtracker.models import * from ietf.iesg.models import * from ietf.idrfc.mails import * from ietf.idrfc.utils import * from ietf.idrfc.lastcall import request_last_call from ietf.ietfworkflows.models import Stream from ietf.ietfworkflows.utils import update_stream from ietf.ietfworkflows.streams import get_stream_from_draft from ietf.doc.models import * from ietf.name.models import IntendedStdLevelName, DocTagName, StreamName from ietf.person.models import Person, Email class ChangeStateForm(forms.Form): pass @group_required('Area_Director','Secretariat') def change_state(request, name): pass IESG_SUBSTATE_TAGS = ('point', 'ad-f-up', 'need-rev', 'extpty') class ChangeStateFormREDESIGN(forms.Form): state = forms.ModelChoiceField(State.objects.filter(type="draft-iesg"), empty_label=None, required=True) substate = forms.ModelChoiceField(DocTagName.objects.filter(slug__in=IESG_SUBSTATE_TAGS), required=False) comment = forms.CharField(widget=forms.Textarea, required=False) @group_required('Area_Director','Secretariat') def change_stateREDESIGN(request, name): """Change state of Internet Draft, notifying parties as necessary and logging the change as a comment.""" doc = get_object_or_404(Document, docalias__name=name) if (not doc.latest_event(type="started_iesg_process")) or doc.get_state_slug() == "expired": raise Http404() login = request.user.get_profile() if request.method == 'POST': form = ChangeStateForm(request.POST) if form.is_valid(): state = form.cleaned_data['state'] tag = form.cleaned_data['substate'] comment = form.cleaned_data['comment'].strip() prev = doc.get_state("draft-iesg") # tag handling is a bit awkward since the UI still works # as if IESG tags are a substate prev_tag = doc.tags.filter(slug__in=('point', 'ad-f-up', 'need-rev', 'extpty')) prev_tag = prev_tag[0] if prev_tag else None if state != prev or tag != prev_tag: save_document_in_history(doc) doc.set_state(state) if prev_tag: doc.tags.remove(prev_tag) if tag: doc.tags.add(tag) e = log_state_changed(request, doc, login, prev, prev_tag) if comment: c = DocEvent(type="added_comment") c.doc = doc c.by = login c.desc = comment c.save() e.desc += "
" + comment doc.time = e.time doc.save() email_state_changed(request, doc, e.desc) email_owner(request, doc, doc.ad, login, e.desc) if state.slug == "lc-req": request_last_call(request, doc) return render_to_response('idrfc/last_call_requested.html', dict(doc=doc, url=doc.get_absolute_url()), context_instance=RequestContext(request)) return HttpResponseRedirect(doc.get_absolute_url()) else: state = doc.get_state("draft-iesg") t = doc.tags.filter(slug__in=('point', 'ad-f-up', 'need-rev', 'extpty')) form = ChangeStateForm(initial=dict(state=state.pk if state else None, substate=t[0].pk if t else None)) state = doc.get_state("draft-iesg") next_states = state.next_states.all() if state else None prev_state = None hists = doc.history_set.exclude(states=doc.get_state("draft-iesg")).order_by('-time')[:1] if hists: prev_state = hists[0].get_state("draft-iesg") to_iesg_eval = None if not doc.latest_event(type="sent_ballot_announcement"): if next_states and next_states.filter(slug="iesg-eva"): to_iesg_eval = State.objects.get(type="draft-iesg", slug="iesg-eva") next_states = next_states.exclude(slug="iesg-eva") return render_to_response('idrfc/change_stateREDESIGN.html', dict(form=form, doc=doc, prev_state=prev_state, next_states=next_states, to_iesg_eval=to_iesg_eval), context_instance=RequestContext(request)) if settings.USE_DB_REDESIGN_PROXY_CLASSES: change_state = change_stateREDESIGN ChangeStateForm = ChangeStateFormREDESIGN class ChangeStreamForm(forms.Form): stream = forms.ModelChoiceField(StreamName.objects.exclude(slug="legacy"), required=False) comment = forms.CharField(widget=forms.Textarea, required=False) @group_required('Area_Director','Secretariat') def change_stream(request, name): """Change the stream of a Document of type 'draft' , notifying parties as necessary and logging the change as a comment.""" doc = get_object_or_404(Document, docalias__name=name) if not doc.type_id=='draft': raise Http404() login = request.user.get_profile() if request.method == 'POST': form = ChangeStreamForm(request.POST) if form.is_valid(): new_stream = form.cleaned_data['stream'] comment = form.cleaned_data['comment'].strip() old_stream = doc.stream if new_stream != old_stream: save_document_in_history(doc) doc.stream = new_stream e = DocEvent(doc=doc,by=login,type='changed_document') e.desc = u"Stream changed to %s from %s"% (new_stream,old_stream) e.save() email_desc = e.desc if comment: c = DocEvent(doc=doc,by=login,type="added_comment") c.desc = comment c.save() email_desc += "\n"+c.desc doc.time = e.time doc.save() email_stream_changed(request, doc, old_stream, new_stream, email_desc) return HttpResponseRedirect(doc.get_absolute_url()) else: stream = doc.stream form = ChangeStreamForm(initial=dict(stream=stream)) return render_to_response('idrfc/change_stream.html', dict(form=form, doc=doc, ), context_instance=RequestContext(request)) class ChangeIntentionForm(forms.Form): intended_std_level = forms.ModelChoiceField(IntendedStdLevelName.objects.filter(used=True), empty_label="(None)", required=True, label="Intended RFC status") comment = forms.CharField(widget=forms.Textarea, required=False) @group_required('Area_Director','Secretariat') def change_intention(request, name): """Change the intended publication status of a Document of type 'draft' , notifying parties as necessary and logging the change as a comment.""" doc = get_object_or_404(Document, docalias__name=name) if not doc.type_id=='draft': raise Http404() login = request.user.get_profile() if request.method == 'POST': form = ChangeIntentionForm(request.POST) if form.is_valid(): new_level = form.cleaned_data['intended_std_level'] comment = form.cleaned_data['comment'].strip() old_level = doc.intended_std_level if new_level != old_level: save_document_in_history(doc) doc.intended_std_level = new_level e = DocEvent(doc=doc,by=login,type='changed_document') e.desc = u"Intended Status changed to %s from %s"% (new_level,old_level) e.save() email_desc = e.desc if comment: c = DocEvent(doc=doc,by=login,type="added_comment") c.desc = comment c.save() email_desc += "\n"+c.desc doc.time = e.time doc.save() email_owner(request, doc, doc.ad, login, email_desc) return HttpResponseRedirect(doc.get_absolute_url()) else: intended_std_level = doc.intended_std_level form = ChangeIntentionForm(initial=dict(intended_std_level=intended_std_level)) return render_to_response('idrfc/change_intended_status.html', dict(form=form, doc=doc, ), context_instance=RequestContext(request)) def dehtmlify_textarea_text(s): return s.replace("
", "\n").replace("", "").replace("", "").replace(" ", " ") class EditInfoForm(forms.Form): pass def get_initial_state_change_notice(doc): # set change state notice to something sensible receivers = [] if doc.group_id == Acronym.INDIVIDUAL_SUBMITTER: for a in doc.authors.all(): # maybe it would be more appropriate to use a.email() ? e = a.person.email()[1] if e: receivers.append(e) else: receivers.append("%s-chairs@%s" % (doc.group.acronym, settings.TOOLS_SERVER)) for editor in doc.group.ietfwg.wgeditor_set.all(): e = editor.person.email()[1] if e: receivers.append(e) receivers.append("%s@%s" % (doc.filename, settings.TOOLS_SERVER)) return ", ".join(receivers) def get_new_ballot_id(): return IDInternal.objects.aggregate(Max('ballot'))['ballot__max'] + 1 @group_required('Area_Director','Secretariat') def edit_info(request, name): pass class EditInfoFormREDESIGN(forms.Form): intended_std_level = forms.ModelChoiceField(IntendedStdLevelName.objects.filter(used=True), empty_label="(None)", required=True, label="Intended RFC status") area = forms.ModelChoiceField(Group.objects.filter(type="area", state="active"), empty_label="(None - individual submission)", required=False, label="Assigned to area") ad = forms.ModelChoiceField(Person.objects.filter(role__name="ad", role__group__state="active").order_by('name'), label="Responsible AD", empty_label="(None)", required=True) create_in_state = forms.ModelChoiceField(State.objects.filter(type="draft-iesg", slug__in=("pub-req", "watching")), empty_label=None, required=False) notify = forms.CharField(max_length=255, label="Notice emails", help_text="Separate email addresses with commas", required=False) note = forms.CharField(widget=forms.Textarea, label="IESG note", required=False) telechat_date = forms.TypedChoiceField(coerce=lambda x: datetime.datetime.strptime(x, '%Y-%m-%d').date(), empty_value=None, required=False, widget=forms.Select(attrs={'onchange':'make_bold()'})) returning_item = forms.BooleanField(required=False) def __init__(self, *args, **kwargs): super(self.__class__, self).__init__(*args, **kwargs) # if previous AD is now ex-AD, append that person to the list ad_pk = self.initial.get('ad') choices = self.fields['ad'].choices if ad_pk and ad_pk not in [pk for pk, name in choices]: self.fields['ad'].choices = list(choices) + [("", "-------"), (ad_pk, Person.objects.get(pk=ad_pk).plain_name())] # telechat choices dates = [d.date for d in TelechatDate.objects.active().order_by('date')] init = kwargs['initial']['telechat_date'] if init and init not in dates: dates.insert(0, init) self.fields['telechat_date'].choices = [("", "(not on agenda)")] + [(d, d.strftime("%Y-%m-%d")) for d in dates] # returning item is rendered non-standard self.standard_fields = [x for x in self.visible_fields() if x.name not in ('returning_item',)] def clean_note(self): # note is stored munged in the database return self.cleaned_data['note'].replace('\n', '
').replace('\r', '').replace(' ', '  ') def get_initial_notify(doc): # set change state notice to something sensible receivers = [] if doc.group.type_id in ("individ", "area"): for a in doc.authors.all(): receivers.append(a.address) else: receivers.append("%s-chairs@%s" % (doc.group.acronym, settings.TOOLS_SERVER)) for editor in Email.objects.filter(role__name="editor", role__group=doc.group): receivers.append(e.address) receivers.append("%s@%s" % (doc.name, settings.TOOLS_SERVER)) return ", ".join(receivers) @group_required('Area_Director','Secretariat') def edit_infoREDESIGN(request, name): """Edit various Internet Draft attributes, notifying parties as necessary and logging changes as document events.""" doc = get_object_or_404(Document, docalias__name=name) if doc.get_state_slug() == "expired": raise Http404() login = request.user.get_profile() new_document = False if not doc.get_state("draft-iesg"): # FIXME: should probably receive "new document" as argument to view instead of this new_document = True doc.notify = get_initial_notify(doc) e = doc.latest_event(TelechatDocEvent, type="scheduled_for_telechat") initial_telechat_date = e.telechat_date if e else None initial_returning_item = bool(e and e.returning_item) if request.method == 'POST': form = EditInfoForm(request.POST, initial=dict(ad=doc.ad_id, telechat_date=initial_telechat_date)) if form.is_valid(): save_document_in_history(doc) r = form.cleaned_data if new_document: doc.set_state(r['create_in_state']) # fix so Django doesn't barf in the diff below because these # fields can't be NULL doc.ad = r['ad'] replaces = Document.objects.filter(docalias__relateddocument__source=doc, docalias__relateddocument__relationship="replaces") if replaces: # this should perhaps be somewhere else, e.g. the # place where the replace relationship is established? e = DocEvent() e.type = "added_comment" e.by = Person.objects.get(name="(System)") e.doc = doc e.desc = "Earlier history may be found in the Comment Log for %s" % (replaces[0], replaces[0].get_absolute_url()) e.save() e = DocEvent() e.type = "started_iesg_process" e.by = login e.doc = doc e.desc = "IESG process started in state %s" % doc.get_state("draft-iesg").name e.save() orig_ad = doc.ad changes = [] def desc(attr, new, old): entry = "%(attr)s changed to %(new)s from %(old)s" if new_document: entry = "%(attr)s changed to %(new)s" return entry % dict(attr=attr, new=new, old=old) def diff(attr, name): v = getattr(doc, attr) if r[attr] != v: changes.append(desc(name, r[attr], v)) setattr(doc, attr, r[attr]) # update the attributes, keeping track of what we're doing diff('intended_std_level', "Intended Status") diff('ad', "Responsible AD") diff('notify', "State Change Notice email list") if r['note'] != doc.note: if not r['note']: if doc.note: changes.append("Note field has been cleared") else: if doc.note: changes.append("Note changed to '%s'" % r['note']) else: changes.append("Note added '%s'" % r['note']) doc.note = r['note'] if doc.group.type_id in ("individ", "area"): if not r["area"]: r["area"] = Group.objects.get(type="individ") if r["area"] != doc.group: if r["area"].type_id == "area": changes.append(u"Assigned to %s" % r["area"].name) else: changes.append(u"No longer assigned to any area") doc.group = r["area"] for c in changes: e = DocEvent(doc=doc, by=login) e.desc = c e.type = "changed_document" e.save() update_telechat(request, doc, login, r['telechat_date'], r['returning_item']) doc.time = datetime.datetime.now() if changes and not new_document: email_owner(request, doc, orig_ad, login, "\n".join(changes)) doc.save() return HttpResponseRedirect(doc.get_absolute_url()) else: init = dict(intended_std_level=doc.intended_std_level_id, area=doc.group_id, ad=doc.ad_id, notify=doc.notify, note=dehtmlify_textarea_text(doc.note), telechat_date=initial_telechat_date, returning_item=initial_returning_item, ) form = EditInfoForm(initial=init) # optionally filter out some fields if not new_document: form.standard_fields = [x for x in form.standard_fields if x.name != "create_in_state"] if doc.group.type_id not in ("individ", "area"): form.standard_fields = [x for x in form.standard_fields if x.name != "area"] return render_to_response('idrfc/edit_infoREDESIGN.html', dict(doc=doc, form=form, user=request.user, login=login, ballot_issued=doc.latest_event(type="sent_ballot_announcement")), context_instance=RequestContext(request)) if settings.USE_DB_REDESIGN_PROXY_CLASSES: EditInfoForm = EditInfoFormREDESIGN edit_info = edit_infoREDESIGN @group_required('Area_Director','Secretariat') def request_resurrect(request, name): """Request resurrect of expired Internet Draft.""" doc = get_object_or_404(InternetDraft, filename=name) if doc.status.status != "Expired": raise Http404() if not doc.idinternal: doc.idinternal = IDInternal(draft=doc, rfc_flag=type(doc) == Rfc) login = IESGLogin.objects.get(login_name=request.user.username) if request.method == 'POST': email_resurrect_requested(request, doc, login) add_document_comment(request, doc, "Resurrection was requested") doc.idinternal.resurrect_requested_by = login doc.idinternal.save() return HttpResponseRedirect(doc.idinternal.get_absolute_url()) return render_to_response('idrfc/request_resurrect.html', dict(doc=doc, back_url=doc.idinternal.get_absolute_url()), context_instance=RequestContext(request)) @group_required('Area_Director','Secretariat') def request_resurrectREDESIGN(request, name): """Request resurrect of expired Internet Draft.""" doc = get_object_or_404(Document, docalias__name=name) if doc.get_state_slug() != "expired": raise Http404() login = request.user.get_profile() if request.method == 'POST': email_resurrect_requested(request, doc, login) e = DocEvent(doc=doc, by=login) e.type = "requested_resurrect" e.desc = "Resurrection was requested" e.save() return HttpResponseRedirect(doc.get_absolute_url()) return render_to_response('idrfc/request_resurrect.html', dict(doc=doc, back_url=doc.get_absolute_url()), context_instance=RequestContext(request)) if settings.USE_DB_REDESIGN_PROXY_CLASSES: request_resurrect = request_resurrectREDESIGN @group_required('Secretariat') def resurrect(request, name): """Resurrect expired Internet Draft.""" doc = get_object_or_404(InternetDraft, filename=name) if doc.status.status != "Expired": raise Http404() if not doc.idinternal: doc.idinternal = IDInternal(draft=doc, rfc_flag=type(doc) == Rfc) login = IESGLogin.objects.get(login_name=request.user.username) if request.method == 'POST': if doc.idinternal.resurrect_requested_by: email_resurrection_completed(request, doc) add_document_comment(request, doc, "Resurrection was completed") doc.idinternal.resurrect_requested_by = None doc.idinternal.event_date = date.today() doc.idinternal.save() doc.status = IDStatus.objects.get(status="Active") doc.save() return HttpResponseRedirect(doc.idinternal.get_absolute_url()) return render_to_response('idrfc/resurrect.html', dict(doc=doc, back_url=doc.idinternal.get_absolute_url()), context_instance=RequestContext(request)) @group_required('Secretariat') def resurrectREDESIGN(request, name): """Resurrect expired Internet Draft.""" doc = get_object_or_404(Document, docalias__name=name) if doc.get_state_slug() != "expired": raise Http404() login = request.user.get_profile() if request.method == 'POST': save_document_in_history(doc) e = doc.latest_event(type__in=('requested_resurrect', "completed_resurrect")) if e and e.type == 'requested_resurrect': email_resurrection_completed(request, doc, requester=e.by) e = DocEvent(doc=doc, by=login) e.type = "completed_resurrect" e.desc = "Resurrection was completed" e.save() doc.set_state(State.objects.get(type="draft", slug="active")) doc.expires = datetime.datetime.now() + datetime.timedelta(settings.INTERNET_DRAFT_DAYS_TO_EXPIRE) doc.time = datetime.datetime.now() doc.save() return HttpResponseRedirect(doc.get_absolute_url()) return render_to_response('idrfc/resurrect.html', dict(doc=doc, back_url=doc.get_absolute_url()), context_instance=RequestContext(request)) if settings.USE_DB_REDESIGN_PROXY_CLASSES: resurrect = resurrectREDESIGN class AddCommentForm(forms.Form): comment = forms.CharField(required=True, widget=forms.Textarea) @group_required('Area_Director','Secretariat', 'IANA') def add_comment(request, name): """Add comment to Internet Draft.""" doc = get_object_or_404(InternetDraft, filename=name) if not doc.idinternal: raise Http404() login = IESGLogin.objects.get(login_name=request.user.username) if request.method == 'POST': form = AddCommentForm(request.POST) if form.is_valid(): c = form.cleaned_data['comment'] add_document_comment(request, doc, c) email_owner(request, doc, doc.idinternal.job_owner, login, "A new comment added by %s" % login) return HttpResponseRedirect(doc.idinternal.get_absolute_url()) else: form = AddCommentForm() return render_to_response('idrfc/add_comment.html', dict(doc=doc, form=form, back_url=doc.idinternal.get_absolute_url()), context_instance=RequestContext(request)) @group_required('Area_Director', 'Secretariat', 'IANA') def add_commentREDESIGN(request, name): """Add comment to history of document.""" doc = get_object_or_404(Document, docalias__name=name) login = request.user.get_profile() if request.method == 'POST': form = AddCommentForm(request.POST) if form.is_valid(): c = form.cleaned_data['comment'] e = DocEvent(doc=doc, by=login) e.type = "added_comment" e.desc = c e.save() if doc.type_id == "draft": email_owner(request, doc, doc.ad, login, "A new comment added by %s" % login.name) return HttpResponseRedirect(urlreverse("doc_history", kwargs=dict(name=doc.name))) else: form = AddCommentForm() return render_to_response('idrfc/add_comment.html', dict(doc=doc, form=form), context_instance=RequestContext(request)) if settings.USE_DB_REDESIGN_PROXY_CLASSES: add_comment = add_commentREDESIGN class NotifyForm(forms.Form): notify = forms.CharField(max_length=255, label="Notice emails", help_text="Separate email addresses with commas", required=False) @group_required('Area_Director','Secretariat') def edit_notices(request, name): """Change the set of email addresses document change notificaitions go to.""" doc = get_object_or_404(Document, type="draft", name=name) if request.method == 'POST': if "save_addresses" in request.POST: form = NotifyForm(request.POST) if form.is_valid(): doc.notify = form.cleaned_data['notify'] doc.save() login = request.user.get_profile() c = DocEvent(type="added_comment", doc=doc, by=login) c.desc = "Notification list changed to : "+doc.notify c.save() return HttpResponseRedirect(urlreverse('doc_view', kwargs={'name': doc.name})) elif "regenerate_addresses" in request.POST: init = { "notify" : get_initial_notify(doc) } form = NotifyForm(initial=init) # Protect from handcrufted POST else: init = { "notify" : doc.notify } form = NotifyForm(initial=init) else: init = { "notify" : doc.notify } form = NotifyForm(initial=init) return render_to_response('idrfc/change_notify.html', {'form': form, 'doc': doc, }, context_instance = RequestContext(request)) class TelechatForm(forms.Form): telechat_date = forms.TypedChoiceField(coerce=lambda x: datetime.datetime.strptime(x, '%Y-%m-%d').date(), empty_value=None, required=False) returning_item = forms.BooleanField(required=False) def __init__(self, *args, **kwargs): super(self.__class__, self).__init__(*args, **kwargs) dates = [d.date for d in TelechatDate.objects.active().order_by('date')] init = kwargs['initial'].get("telechat_date") if init and init not in dates: dates.insert(0, init) self.fields['telechat_date'].choices = [("", "(not on agenda)")] + [(d, d.strftime("%Y-%m-%d")) for d in dates] @group_required("Area Director", "Secretariat") def telechat_date(request, name): doc = get_object_or_404(Document, type="draft", name=name) login = request.user.get_profile() e = doc.latest_event(TelechatDocEvent, type="scheduled_for_telechat") initial_returning_item = bool(e and e.returning_item) initial = dict(telechat_date=e.telechat_date if e else None, returning_item = initial_returning_item, ) if request.method == "POST": form = TelechatForm(request.POST, initial=initial) if form.is_valid(): update_telechat(request, doc, login, form.cleaned_data['telechat_date'],form.cleaned_data['returning_item']) return HttpResponseRedirect(urlreverse('doc_view', kwargs={'name': doc.name})) else: form = TelechatForm(initial=initial) return render_to_response('idrfc/edit_telechat_date.html', dict(doc=doc, form=form, user=request.user, login=login), context_instance=RequestContext(request)) class IESGNoteForm(forms.Form): note = forms.CharField(widget=forms.Textarea, label="IESG note", required=False) def clean_note(self): # note is stored munged in the database return self.cleaned_data['note'].replace('\n', '
').replace('\r', '').replace(' ', '  ') @group_required("Area Director", "Secretariat") def edit_iesg_note(request, name): doc = get_object_or_404(Document, type="draft", name=name) login = request.user.get_profile() initial = dict(note=dehtmlify_textarea_text(doc.note)) if request.method == "POST": form = IESGNoteForm(request.POST, initial=initial) if form.is_valid(): new_note = form.cleaned_data['note'] if new_note != doc.note: if not new_note: if doc.note: log_message = "Note field has been cleared" else: if doc.note: log_message = "Note changed to '%s'" % new_note else: log_message = "Note added '%s'" % new_note doc.note = new_note doc.save() c = DocEvent(type="added_comment", doc=doc, by=login) c.desc = log_message c.save() return HttpResponseRedirect(urlreverse('doc_view', kwargs={'name': doc.name})) else: form = IESGNoteForm(initial=initial) return render_to_response('idrfc/edit_iesg_note.html', dict(doc=doc, form=form, ), context_instance=RequestContext(request)) class AdForm(forms.Form): ad = forms.ModelChoiceField(Person.objects.filter(role__name="ad", role__group__state="active").order_by('name'), label="Shepherding AD", empty_label="(None)", required=True) def __init__(self, *args, **kwargs): super(self.__class__, self).__init__(*args, **kwargs) # if previous AD is now ex-AD, append that person to the list ad_pk = self.initial.get('ad') choices = self.fields['ad'].choices if ad_pk and ad_pk not in [pk for pk, name in choices]: self.fields['ad'].choices = list(choices) + [("", "-------"), (ad_pk, Person.objects.get(pk=ad_pk).plain_name())] @group_required("Area Director", "Secretariat") def edit_ad(request, name): """Change the shepherding Area Director for this draft.""" doc = get_object_or_404(Document, type="draft", name=name) if request.method == 'POST': form = AdForm(request.POST) if form.is_valid(): doc.ad = form.cleaned_data['ad'] doc.save() login = request.user.get_profile() c = DocEvent(type="added_comment", doc=doc, by=login) c.desc = "Shepherding AD changed to "+doc.ad.name c.save() return HttpResponseRedirect(urlreverse('doc_view', kwargs={'name': doc.name})) else: init = { "ad" : doc.ad_id } form = AdForm(initial=init) return render_to_response('idrfc/change_ad.html', {'form': form, 'doc': doc, }, context_instance = RequestContext(request))