form投稿時にユーザ情報を外部キーを自動的に設定する

環境

  • django 1.8.7
  • python 3.4.1

ユーザがform 投稿する時に、外部キーを自動的に設定したい。しかも、ユーザには意識させずに。

例えば、次のようなUser を外部キーにもつTweet のデータがあるとする。

form を投稿した人を自動的にowner にするようにする。

修正前

//models.py

class Tweet(models.Model):
    ''' project to be donated'''
    name   = models.CharField(max_length=100) 
    owner  = models.ForeignKey(User)
    text   = models.TextField(blank=True)
    categories  = models.CharField(max_length=100,blank=True)
    created_at    = models.DateTimeField(auto_now_add=True, blank=True)
    updated_at    = models.DateTimeField(auto_now=True, blank=True)
    terminated_at = models.DateTimeField(auto_now=True, blank=True)

    def __unicode__():
        return self.name

修正後

// views.py

from .models import Tweet, TweetCreateForm
from django.contrib.auth import User


@login_required
def tweet_create(request):
    p = Tweet(owner=User.objects.get(pk=request.user.id))
    form = TweetCreateForm(request.POST or None, instance=p)
    form.save(commit=False)
    if form.is_valid():
        name = form.cleaned_data['name']
        text    = form.cleaned_data['text']

        form.save()
        return HttpResponseRedirect('/')
    else:
        return render(request, 'app/tweet_create.html', {'form': form})

models.py を修正する

// models.py

from django.db import models
from django.forms import ModelForm
from django import forms

class Tweet(models.Model):
    ''' project to be donated'''
    name   = models.CharField(max_length=100) 
    owner  = models.ForeignKey(User, editable=False) # 編集不可にする。form に表示されなくなる。
    text   = models.TextField(blank=True)
    categories  = models.CharField(max_length=100,blank=True)
    created_at    = models.DateTimeField(auto_now_add=True, blank=True)
    updated_at    = models.DateTimeField(auto_now=True, blank=True)
    terminated_at = models.DateTimeField(auto_now=True, blank=True)

    def __unicode__():
        return self.name

class TweetCreateForm(ModelForm):
    class Meta:
        model = Tweet
        fields = '__all__'

foregin key だと デフォルトで全部の選択肢(今回だと全ユーザ)からの選択可能な状態になってしまい、UXが悪い。 ユーザには意識させずに、自動的にひも付けができるのでいい感じかと。

もっと良い書き方があるかもしれないなぁ。。