views:

78

answers:

1

I have a model that contains a foreign key value, then in the form generated from this model as a ModelChoiceField. I want to auto select the user's (update_author). I've tried the below code, using the initial property.

The view creates a formset with the the dates initialized to now() for the empty form. But, I want also the update_author field to be initialized to some value, and it does not work. Even if the dev shell returns the correct user (print), this one is still not selected in the list.

How to initialize a django.forms.ModelChoiceField, binded with foreign key, with a value?


models.py

from django.db import models
import datetime

class Author(models.Model):
    name = models.CharField(max_length=255)
    email = models.CharField(max_length=255)
    def __unicode__(self):
        return self.name


class DataReview(models.Model):
    comments = models.CharField(max_length=255)
    update_author = models.ForeignKey('Author')
    creation_date = models.DateTimeField('date data review created')
    update_date = models.DateTimeField('date review modified')

    def __unicode__(self):
        return "%s" % (self.comments)

forms.py corrected

from bamboo.followup.models import *
from django import forms
from django.forms import ModelForm,Form
from django.forms.extras.widgets import SelectDateWidget
import datetime


class DataReviewForm(ModelForm):


    def __init__(self, *args, **kwargs):
         initial = {
               'update_date': datetime.datetime.now(),
               'creation_date': datetime.datetime.now(),
               'update_author': 1 # not Author.objects.get(id=1)
              }
        if kwargs.has_key('initial'):
            kwargs['initial'].update(initial)
        else:
            kwargs['initial'] = initial
        # Initializing form only after you have set initial dict
        super(DataReviewsForm,self).__init__(*args, **kwargs)
        self.fields['update_date'].widget.attrs['disabled']=''
        self.fields['creation_date'].widget.attrs['disabled']=''
    self.fields['update_author'].widget.attrs['disabled'] = ''

    class Meta:
        model = DataReview

views.py updated

def review(request):
    DataReviewsFormSet = modelformset_factory(DataReview, form=DataReviewsForm)
    if request.method == 'POST':
        formset = DataReviewSet(request.POST)
        if formset.is_valid():
            # do something with the formset.cleaned_dat
            print 'YOUHOU!'
    else:
        formset = DataReviewSet()
    return render_to_response('followup/runs.html', {
        "formset": formset,
        })
A: 

For the core of your question is, as to how to set initial value for ForeignKey field, check the code snippet below.

Note that when you provide initial value to a ForeignKey field, you don't need to pass the object. Pass it the id/pk of that object, and your problem will be solved.

initial = {
           'update_date': datetime.datetime.now(),
           'creation_date': datetime.datetime.now(),
           'update_author': 1 # not Author.objects.get(id=1)
          }
if kwargs.has_key('initial'):
    kwargs['initial'].update(initial)
else:
    kwargs['initial'] = initial
# Initializing form only after you have set initial dict
super(DataReviewsForm,self).__init__(*args, **kwargs)

self.fields['update_date'].widget = forms.HiddenInput()
self.fields['creation_date'].widget = forms.HiddenInput()
self.fields['update_author'].widget = forms.HiddenInput()

A lot cleaner way to do it.

Disabling the fields As Form exposes 'fields widgets' only after invoking constructor, any updation [be it widget override, or changing attributes of widget], can be done only after that. Or, you can do it in form field definition, which doesn't apply on your case. In short, disabling the field is better after super constructor call.

simplyharsh
Thank you. Your suggestion works. Why updating initial before invoking the super class's constructor, as you did, works better? How can I apply your style to the 'disabled' field?
djondal
Check the update.
simplyharsh
I updated the question with the current code. "Disabling the field is better after super constructor call." The fields are properly disabled. But when submitting the form, I get the message: "This field is required.", even though that field is auto populated
djondal
forms.HiddenInput() makes the field not visible. I would like it visible but not editable.
djondal