21

I'm trying to create a dialog which uses jquery's .load() function to slurp in a rendered django form. The .load function is passed the pk of the "alert" object. Also available in the class functions are things like self.request.user so I can pre-fill those fields, shown below in the Message model (models.py):

class Message(models.Model):

    user = models.ForeignKey(User)
    alert = models.ForeignKey(Alert)
    date = models.DateTimeField()
    message = models.TextField()

Subclassing django's CreateView makes it pretty easy to generate a context with an instance of the ModelForm (views.py):

class MessageDialogView(CreateView):
    """ show html form fragment """
    model = Message
    template_name = "message.html"

    def get_initial(self):
        super(MessageDialogView, self).get_initial()
        alert = Alert.objects.get(pk=self.request.POST.get("alert_id"))
        user = self.request.user
        self.initial = {"alert":alert.id, "user":user.id, "message":"test"}
        return self.initial


    def post(self, request, *args, **kwargs):
        super(MessageDialogView, self).post(request, *args, **kwargs)
        form_class = self.get_form_class()
        form = self.get_form(form_class)
        context = self.get_context_data(form=form)
        return self.render_to_response(context)

The problem here is that self.initial does not get rendered with the form. I have insured that the form is indeed calling get_initial and the form instance has the proper initial data in post, but when the form is rendered in the template message.html it doesn't grab any of the initial data like I would expect. Is there a special trick to get this to work? I've scoured the docs (seems to be lacking examples on generic based class views) and source but I can't see what I'm missing.

Grzegorz Rożniecki
  • 27,415
  • 11
  • 90
  • 112
Matt
  • 249
  • 1
  • 2
  • 8

3 Answers3

30

get_initial() should just return a dictionary, not be bothered with setting self.initial.

Your method should look something like this:

def get_initial(self):
    # Get the initial dictionary from the superclass method
    initial = super(YourView, self).get_initial()
    # Copy the dictionary so we don't accidentally change a mutable dict
    initial = initial.copy()
    initial['user'] = self.request.user.pk
       # etc...
    return initial
SmileyChris
  • 10,578
  • 4
  • 40
  • 33
  • 1
    Pardon my ignorance but what's the risk of not copying the dictionary? – Harry Jan 13 '14 at 14:58
  • @HarryGordon try this: dict1 = {'a':1,'b':2} dict2 = dict1 dict2['b']=10 print(dict1) – Zhe Li Feb 06 '14 at 13:32
  • looks like all the newlines are lost :( – Zhe Li Feb 06 '14 at 13:34
  • 2
    Thanks Zhe but I don't understand why the copy is important in this particular case - wouldn't that only be important if the object is still in use elsewhere...? – Harry Feb 06 '14 at 18:00
  • @HarryGordon Because it is defined like this [in the source](https://github.com/django/django/blob/stable/1.10.x/django/views/generic/edit.py#L21). – raratiru Oct 17 '16 at 23:37
1

you can use like :

from django.shortcuts import HttpResponseRedirect

    class PostCreateView(CreateView):
        model = Post
        fields = ('title', 'slug', 'content', 'category', 'image')
        template_name = "create.html"
        success_url = '/'

        def form_valid(self, form):
            self.object = form.save(commit=False)
            self.object.user = self.request.user
            self.object.save()
            return HttpResponseRedirect(self.get_success_url())

that's work for me

hassanzadeh.sd
  • 3,091
  • 1
  • 17
  • 26
0

(Edited because what you're trying does actually work)

I ran into the same problem yesterday, but it's working now – I think I was returning an object instead of a dict in get_initial.

In terms of fixing your problem, I'm a little suspicious of how much you seem to be doing in post() – could you try it with the default (non-overrided) post()?

You could also use pdb (or print statements) to check the value of self.get_form_kwargs make sure that initial is being set.

supervacuo
  • 9,072
  • 2
  • 44
  • 61