如何将表单中的用户字段设置为当前登录的用户?

时间:2013-08-15 04:27:26

标签: django django-forms django-views

我正在制作一个选举信息应用程序,我希望允许当前登录的用户能够宣布自己并且仅自己作为选举中的候选人。

我正在使用Django的内置ModelForm和CreateView。我的问题是Run for Office表单(换句话说,'创建候选人'表单)允许用户选择数据库中的任何用户来制作候选人。

我希望Run for Office中的用户字段自动设置为当前登录的用户,并且要隐藏此值,因此登录用户无法将该字段的值更改为其他人。

views.py

class CandidateCreateView(CreateView):
    model = Candidate
    form_class = CandidateForm
    template_name = 'candidate_create.html'

    def form_valid(self, form):
        f = form.save(commit=False)
        f.save()
        return super(CandidateCreateView, self).form_valid(form)

forms.py

class CandidateForm(forms.ModelForm):
    class Meta:
        model = Candidate

models.py

class Candidate(models.Model):
    user = models.ForeignKey(UserProfile)
    office = models.ForeignKey(Office)
    election = models.ForeignKey(Election)
    description = models.TextField()

    def __unicode__(self):
        return unicode(self.user)

    def get_absolute_url(self):
        return reverse('candidate_detail', kwargs={'pk': str(self.id)})

2 个答案:

答案 0 :(得分:39)

  1. 从呈现的表单中删除用户字段(使用excludefieldshttps://docs.djangoproject.com/en/dev/topics/forms/modelforms/#selecting-the-fields-to-use

    class CandidateForm(forms.ModelForm):
        class Meta:
            model = Candidate
            exclude = ["user"]
    
  2. 在创建视图中查找用户个人资料并设置用户字段。

    class CandidateCreateView(CreateView):
        ...
        def form_valid(self, form):
            candidate = form.save(commit=False)
            candidate.user = UserProfile.objects.get(user=self.request.user)  # use your own profile here
            candidate.save()
            return HttpResponseRedirect(self.get_success_url())
    

答案 1 :(得分:2)

假设

  1. 我们不想设置null=True,因为我们不想在模型和/或数据库级别允许null用户

  2. 我们不想设置blank=True来破坏模型的可读性,因为用户实际上不会空白

@ nbm.ten 解决方案是一个很好的解决方案。与使用nbm中的 model 设置用户(例如this one)的该问题相比,该解决方案的其他解决方案具有优势。ten不会破坏上述假设。我们不想弄乱模型来解决问题!

但是在这里,我基于django文档(Models and request.user)添加了另外两个解决方案:

另外两个解决方案

1。使用通用的CreateView

from django.contrib.auth.mixins import LoginRequiredMixin
from django.views.generic.edit import CreateView
from myapp.models import Candidate

class CandidateCreate(LoginRequiredMixin, CreateView):
    model = Candidate
    exclude = ['user']

    def form_valid(self, form):
        form.instance.user = self.request.user
        return super().form_valid(form)

2。使用基于类的视图

class CandidateForm(ModelForm):
    class Meta:
        model = Candidate
        exclude = [ 'user',]

class CandidateAddView(LoginRequiredMixin, View):
    def get(self, request, *args, **kwargs):
        form = CandidateForm()
        context = {'form':form}
        return render(request, 'myapp/addcandidateview.html', context)
    
    def post(self, request, *args, **kwargs):
           
        form = CandidateForm(request.POST)
        form.instance.user = request.user
        if form.is_valid():
            form.save()
            return redirect(reverse('myapp:index'))

注释

  • 请注意, LoginRequiredMixin 会阻止未登录的用户访问表单。如果我们忽略了这一点,则需要处理form_valid()post()中的未授权用户。

  • exclude = ['user']阻止用户字段显示在表单上。

  • 我们使用form.instance.user将用户设置为form.dataform.cleaned_data无效的用户