jpaugh
jpaugh

Reputation: 7035

Django, class-views: How can I save session data with a form's object?

I'm trying to store the username from the current request's session into a db object. How can I do this from within a class-based view? Is there a "clean" way to do this? What should I override/subclass?

I have a model that looks like this:

from django.contrib.auth.models import User
class Entry(django.db.models.Model):
  ...
  author = models.ForeignKey(User, editable=False)

I also have a view based on the built-in generic view django.views.generic.CreateView. I'm also using the default ModelForm class that goes with my model, and the default {{ form }} in my template. AFAIK, the session and authentication apps/middleware are set up properly---as per default in new Django projects.

I found this post, which is getting at about the same thing, but from the wrong angle, and using function views instead.

My thinking so far was to override something in the form class and insert the username into the cleaned data. Is there a better way? Is there a right way?

Edit: Solution so far, non-working, with an IntegrityError: author_id cannot be null

from django.views.generic import CreateView

class Index(CreateView):
  model = magicModel
  template_name = "index.html"
  success_url = "/magicWorked"
  ...
  def form_valid(self, form):
    self.object = form.save(commit=False)
    self.object.author = request.user
    return super(Index, self).form_valid(form)

I wrote this based on what I found in django/views/generic/edit.py, which uses this implementation for class ModelFormMixin:

def form_valid(self, form):
  self.object = form.save()
  return super(ModelFormMixin, self).form_valid(form)

This is the method called by super().form_valid() above.

Edit: The problem with my solution was my understanding of Python's inheritance model. When the super-class calls form_valid(), it calls its own version, not my override; my code was never running at all.

Upvotes: 1

Views: 1748

Answers (2)

jpaugh
jpaugh

Reputation: 7035

Incidentally, Django's 1.3 docs say somewhere in there that modifications to the authentication model used by the admin app are being "discussed," such as adding per-instance permissions. (The current auth model supports only per model permissions.) The dev's might also add an implementation for what I'm trying to achieve. After all, user-associated data is used by nearly all websites.

Upvotes: 0

jeffknupp
jeffknupp

Reputation: 6274

The "correct" way to do this is to write your own view for object creation if the generic view doesn't suffice. Creation views are relatively short and there are numerous examples of how to save foreign keys.

Upvotes: 1

Related Questions