限制 CreateView 中的表单字段不将当前用户显示为模板中的选项
Restrict form field in CreateView to not show current-user as a choice in template
我使用简单的表格和通用的 CBV UpdateView 来让所有用户使用 "tokens" 给其他用户额外的信用。不应允许用户给自己额外的信用,因此他们不应出现在 select 字段中作为选择。我在这里没有使用模型表单,想知道如何在不这样做的情况下执行此操作。到目前为止,这是我的代码:
models.py
class ExtraCredit(models.Model):
recipient = models.ForeignKey(Developer, related_name='extracredit_recipient')
sender = models.ForeignKey(Developer, related_name='extracredit_sender')
skill = models.ForeignKey(Skill, related_name='extracredit_skill')
description = models.TextField(blank=True, null=True)
date_credited = models.DateField(auto_now_add=True)
def __str__(self):
return '%s %s -> %s %s - %s' % (self.sender.user.first_name, self.recipient.user.last_name, self.recipient.user.first_name, self.recipient.user.last_name, self.skill.name)
views.py
class ExtraCreditCreateView(CreateView):
model = ExtraCredit
template_name = 'extracredit_create.html'
def __init__(self, *args, **kwargs):
user = kwargs.pop('user', None)
super(ExtraCreditCreateView, self).__init__(*args, **kwargs)
self.fields['recipient'].queryset = ExtraCredit.objects.exclude(recipient=user)
self.fields['description'].help_text = "Why does this user deserve extra credit?"
def get_form_kwargs(self):
kwargs = super(ExtraCreditCreateView, self).get_form_kwargs()
kwargs.update({'user': self.request.user})
return kwargs
def get_success_url(self):
return reverse('my_developer_details')
def form_invalid(self, form):
return self.render_to_response(self.get_context_data(form=form))
def form_valid(self, form):
form.save(commit=False)
sender = get_object_or_404(Developer, user_id=self.request.user.id)
extra_credit_tokens = Developer.objects.get(user_id=sender.user_id).extra_credit_tokens
if extra_credit_tokens:
Developer.objects.filter(user_id=sender.user_id).update(extra_credit_tokens=extra_credit_tokens-1)
form.instance.sender = sender
form.save()
return super(ExtraCreditCreateView, self).form_valid(form)
else:
raise forms.ValidationError("The user does not have enough tokens")
fields = ['recipient', 'skill', 'description']
我拥有get_form_kwargs(self)
函数的唯一原因是尝试在def __init__
函数中使用self.request.user
。如果我在 __init__
函数中使用 self.request.user,我会得到一个错误,指出请求不是 ExtraCreditCreateView
的属性。如果我确实向选项添加了请求,例如 __init__(self, request, *args, **kwargs):
,那么我会收到一个关于需要两个参数并且只提供一个参数的错误。现在设置的方式,我得到一个 TypeError: list indices must be integers, not str
.
在模板中创建表单时确保当前登录用户不在 'recipient' 字段中的正确方法是什么?
更新的解决方案(基于@Alasdair 的回答):
class ExtraCreditForm(forms.ModelForm):
class Meta:
model = ExtraCredit
exclude = ['id', 'sender', 'date_credited']
def __init__(self, *args, **kwargs):
user = kwargs.pop('user', None)
super(ExtraCreditForm, self).__init__(*args, **kwargs)
self.fields['recipient'].queryset = self.fields['recipient'].queryset.exclude(user_id=user.id)
self.fields['description'].help_text = "Why does this user deserve extra credit?"
class ExtraCreditCreateView(CreateView):
template_name = 'extracredit_create.html'
form_class = ExtraCreditForm
def get_form_kwargs(self):
kwargs = super(ExtraCreditCreateView, self).get_form_kwargs()
kwargs.update({'user': self.request.user})
return kwargs
def get_success_url(self):
return reverse('my_developer_details')
def form_valid(self, form):
form.save(commit=False)
sender = get_object_or_404(Developer, user_id=self.request.user.id)
extra_credit_tokens = Developer.objects.get(user_id=sender.user_id).extra_credit_tokens
if extra_credit_tokens:
Developer.objects.filter(user_id=sender.user_id).update(extra_credit_tokens=extra_credit_tokens-1)
form.instance.sender = sender
form.save()
return super(ExtraCreditCreateView, self).form_valid(form)
else:
raise forms.ValidationError("The user does not have enough tokens")
你说你想避免定义模型表单,但这是最好的方法。 可能可以在 get_form
方法中破解表单的字段,但您不应该这样做。
设置收件人的查询集属于表单,而不是视图的 __init__
方法。
class ExtraCreditForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
user = kwargs.pop('user', None)
super(ExtraCreditForm, self).__init__(*args, **kwargs)
self.fields['recipient'].queryset = ExtraCredit.objects.exclude(recipient=user)
self.fields['description'].help_text = "Why does this user deserve extra credit?"
然后从您的视图中删除 __init__
方法,并设置 form_class
以便它使用您的模型表单。您已经更新 get_form_kwargs
以将用户传递给表单的 __init__
方法,因此您不必进行任何其他更改。您的 form_invalid
方法没有做任何特别的事情,因此您可以将其删除。
class ExtraCreditCreateView(CreateView):
form_class = ExtraCreditForm
...
我使用简单的表格和通用的 CBV UpdateView 来让所有用户使用 "tokens" 给其他用户额外的信用。不应允许用户给自己额外的信用,因此他们不应出现在 select 字段中作为选择。我在这里没有使用模型表单,想知道如何在不这样做的情况下执行此操作。到目前为止,这是我的代码:
models.py
class ExtraCredit(models.Model):
recipient = models.ForeignKey(Developer, related_name='extracredit_recipient')
sender = models.ForeignKey(Developer, related_name='extracredit_sender')
skill = models.ForeignKey(Skill, related_name='extracredit_skill')
description = models.TextField(blank=True, null=True)
date_credited = models.DateField(auto_now_add=True)
def __str__(self):
return '%s %s -> %s %s - %s' % (self.sender.user.first_name, self.recipient.user.last_name, self.recipient.user.first_name, self.recipient.user.last_name, self.skill.name)
views.py
class ExtraCreditCreateView(CreateView):
model = ExtraCredit
template_name = 'extracredit_create.html'
def __init__(self, *args, **kwargs):
user = kwargs.pop('user', None)
super(ExtraCreditCreateView, self).__init__(*args, **kwargs)
self.fields['recipient'].queryset = ExtraCredit.objects.exclude(recipient=user)
self.fields['description'].help_text = "Why does this user deserve extra credit?"
def get_form_kwargs(self):
kwargs = super(ExtraCreditCreateView, self).get_form_kwargs()
kwargs.update({'user': self.request.user})
return kwargs
def get_success_url(self):
return reverse('my_developer_details')
def form_invalid(self, form):
return self.render_to_response(self.get_context_data(form=form))
def form_valid(self, form):
form.save(commit=False)
sender = get_object_or_404(Developer, user_id=self.request.user.id)
extra_credit_tokens = Developer.objects.get(user_id=sender.user_id).extra_credit_tokens
if extra_credit_tokens:
Developer.objects.filter(user_id=sender.user_id).update(extra_credit_tokens=extra_credit_tokens-1)
form.instance.sender = sender
form.save()
return super(ExtraCreditCreateView, self).form_valid(form)
else:
raise forms.ValidationError("The user does not have enough tokens")
fields = ['recipient', 'skill', 'description']
我拥有get_form_kwargs(self)
函数的唯一原因是尝试在def __init__
函数中使用self.request.user
。如果我在 __init__
函数中使用 self.request.user,我会得到一个错误,指出请求不是 ExtraCreditCreateView
的属性。如果我确实向选项添加了请求,例如 __init__(self, request, *args, **kwargs):
,那么我会收到一个关于需要两个参数并且只提供一个参数的错误。现在设置的方式,我得到一个 TypeError: list indices must be integers, not str
.
在模板中创建表单时确保当前登录用户不在 'recipient' 字段中的正确方法是什么?
更新的解决方案(基于@Alasdair 的回答):
class ExtraCreditForm(forms.ModelForm):
class Meta:
model = ExtraCredit
exclude = ['id', 'sender', 'date_credited']
def __init__(self, *args, **kwargs):
user = kwargs.pop('user', None)
super(ExtraCreditForm, self).__init__(*args, **kwargs)
self.fields['recipient'].queryset = self.fields['recipient'].queryset.exclude(user_id=user.id)
self.fields['description'].help_text = "Why does this user deserve extra credit?"
class ExtraCreditCreateView(CreateView):
template_name = 'extracredit_create.html'
form_class = ExtraCreditForm
def get_form_kwargs(self):
kwargs = super(ExtraCreditCreateView, self).get_form_kwargs()
kwargs.update({'user': self.request.user})
return kwargs
def get_success_url(self):
return reverse('my_developer_details')
def form_valid(self, form):
form.save(commit=False)
sender = get_object_or_404(Developer, user_id=self.request.user.id)
extra_credit_tokens = Developer.objects.get(user_id=sender.user_id).extra_credit_tokens
if extra_credit_tokens:
Developer.objects.filter(user_id=sender.user_id).update(extra_credit_tokens=extra_credit_tokens-1)
form.instance.sender = sender
form.save()
return super(ExtraCreditCreateView, self).form_valid(form)
else:
raise forms.ValidationError("The user does not have enough tokens")
你说你想避免定义模型表单,但这是最好的方法。 可能可以在 get_form
方法中破解表单的字段,但您不应该这样做。
设置收件人的查询集属于表单,而不是视图的 __init__
方法。
class ExtraCreditForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
user = kwargs.pop('user', None)
super(ExtraCreditForm, self).__init__(*args, **kwargs)
self.fields['recipient'].queryset = ExtraCredit.objects.exclude(recipient=user)
self.fields['description'].help_text = "Why does this user deserve extra credit?"
然后从您的视图中删除 __init__
方法,并设置 form_class
以便它使用您的模型表单。您已经更新 get_form_kwargs
以将用户传递给表单的 __init__
方法,因此您不必进行任何其他更改。您的 form_invalid
方法没有做任何特别的事情,因此您可以将其删除。
class ExtraCreditCreateView(CreateView):
form_class = ExtraCreditForm
...