32

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

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

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

视图.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)

表格.py

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

模型.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)})
4

2 回答 2

55
  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())
    
于 2013-08-15T05:53:59.197 回答
6

假设

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

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

@nbm.ten解决方案是一个很好的解决方案。对于这个问题,它比其他“解决方案”具有优势,即利用模型在 nbm.ten中设置用户(如这个)并不会破坏上述假设。我们不想弄乱模型来修复视图中的问题!

但在这里我添加了两个基于 django 文档(Models 和 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()or中处理未经授权的用户post()

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

  • 我们曾经form.instance.user设置用户不form.dataform.cleaned_data他们不工作

于 2020-07-04T09:10:22.030 回答