Django 表单和 CBV CreateView 无法将 request.user 分配给用户字段
Django form and CBV CreateView not able to assign request.user to user field
我有一个表单和一个 CBV CreateView。我需要将 request.user 分配给用户字段(CustomUser 模型的外键),它在表单中是一个隐藏字段(用户)。但是,我尝试使用 "self.fields['user'] = self.request.user.id" 形式的 init 方法,但出现错误:'NoneType' 对象没有属性 'user'。实现此目标的最简洁方法是什么?
我尝试了很多不同的方法,但都没有成功。 ):
这是我的表格:
class PhoneForm(forms.ModelForm):
class Meta:
model = Phone
fields = 'user', 'phone_name', 'country', 'phone_number', 'phone_type', 'primary'
widgets = {'user': forms.HiddenInput()}
def __init__(self, *args, **kwargs):
self.request = kwargs.pop('request', None)
super(PhoneForm, self).__init__(*args, **kwargs)
self.fields['user'].widget.attrs['readonly'] = True
self.fields['user'] = self.request.user.id
self.fields['primary'].help_text = _('<strong>Check:</strong> If this is your main contact phone number.')
def clean(self):
cleaned_data = super(PhoneForm, self).clean()
user = cleaned_data.get('user')
phone_name = cleaned_data.get('phone_name')
country = cleaned_data.get('country')
phone_number = cleaned_data.get('phone_number')
phone_type = cleaned_data.get('phone_type')
primary = cleaned_data.get('primary')
print('user: ',user)
print('phone_name: ',phone_name)
print('country: ',country)
print('phone_number: ',phone_number)
print('phoe_type: ',phone_type)
print('primary: ',primary)
if "action_add" in self.request.POST:
try:
phonenum = Phone.objects.filter(user=user, country=country, phone_number=phone_number).first()
if phonenum:
raise forms.ValidationError(_('This Phone is registered already.'))
except Phone.DoesNotExist:
pass
try:
phone = Phone.objects.filter(user=user, primary=True).first()
if phone and primary:
raise forms.ValidationError(_('There is another "Primary" Phone #already.'), code='invalid')
except Phone.DoesNotExist:
pass
if "action_update" in self.request.POST:
if "country" in self.changed_data or "phone_number" in self.changed_data:
raise forms.ValidationError(_('You can´t update the Country nor the Phone number of the existing Phone.'))
try:
phone = Phone.objects.filter(user=user, primary=True).first()
if phone and primary and self.request.session['Phone_object_id'] != phone.id:
raise forms.ValidationError(_('There is another "Primary" Phone #already.'), code='invalid')
except Phone.DoesNotExist:
pass
if not phone_name and not phone_type and not phone_number:
raise forms.ValidationError(_('You have to fill out the form!'))
这是我的观点:
class PhoneCreateView(LoginRequiredMixin, CreateView):
form_class = PhoneForm
model = Phone
template_name = 'phones/addPhone.html'
login_url = reverse_lazy('account_login')
success_url = reverse_lazy('phonesList')
class Meta:
readonly = ('user', )
def get_form_kwargs(self):
kw = super(PhoneCreateView, self).get_form_kwargs()
kw['request'] = self.request
return kw
def get_initial(self):
phone = Phone.create(self.request.user.id)
form = self.form_class(instance=phone)
form.instance.user = CustomUser.objects.get(id=self.request.user.id)
return {'form': form, }
def get_context_data(self, **kwargs):
context = super(PhoneCreateView, self).get_context_data(**kwargs)
form = self.form_class(instance=self.object)
form.instance.user = CustomUser.objects.get(id=self.request.user.id)
context = {
'form': form,
'user': self.request.user.id,
}
return context
def form_valid(self, form):
form.instance.user = CustomUser.objects.get(id=self.request.user.id)
form.instance.status = 'A'
form.instance.status_dt = timezone.now()
form.instance.at_user = self.request.user.email
form.instance.at_ip = visitor_ip_address(self.request)
form.instance.at_dttm = timezone.now()
form.instance.at_action = 'Create Phone number'
messages.success(self.request, _('Your Phone Number has been registered.'))
return super(PhoneCreateView, self).form_valid(form)
这是我的模型:
class Phone(models.Model):
PHONETYPES = (
('1', _('Mobile')),
('2', _('Home')),
('3', _('Work')),
('4', _('Other')),
)
status = models.CharField(_("Record Status"), max_length=1, default='A')
status_dt = models.DateTimeField(_("Status Date"), default=timezone.now)
user = models.ForeignKey(CustomUser, verbose_name=_("User"), on_delete=models.CASCADE)
phone_name = models.CharField(_("Phone name"), max_length=20, default="PH"+str(random.randint(1,99999)))
country = models.IntegerField(_("Country Dialing Code"))
phone_number = models.CharField(_("Phone Number"), max_length=11)
phone_type = models.CharField(_("Phone Type"), max_length=1, default="4", choices=PHONETYPES)
verified = models.BooleanField(verbose_name=_('verified'), default=False)
primary = models.BooleanField(verbose_name=_('primary'), default=False)
at_user = models.CharField(_("Audit Trail (user)"), max_length=255, blank=True)
at_ip = models.GenericIPAddressField(_("Audit Trail (IP)"), protocol='both', blank=True, null=True)
at_dttm = models.DateTimeField(_("Audit Trail (Date-Time)"), default=timezone.now)
at_action = models.CharField(_("Audit Trail (Function performed)"), max_length=255, blank=True)
UniqueConstraint(fields=['user', 'country', 'phone_number'], name='user_unique_phone_number')
class Meta:
verbose_name = _("Phone Number")
verbose_name_plural = _("Phone Numbers")
@classmethod
def create(cls, user):
phone = cls(user= get_object_or_404(CustomUser, pk=user))
# phone create
return phone
def __str__(self):
return self.phone_name
我不得不改变一些东西。首先从表单和字段中取出隐藏字段用户(这是用户 table 的外键)。相反,我使用了一个会话参数来存储用户 ID。然后我不得不在视图中重新表述我的方法 get_context_data。以下是更新后的代码:
我的新表格:
class PhoneForm(forms.ModelForm):
class Meta:
model = Phone
fields = 'phone_name', 'country', 'phone_number', 'phone_type', 'primary'
#widgets = {'user': forms.HiddenInput()}
def __init__(self, *args, **kwargs):
self.request = kwargs.pop('request', None)
if self.request is None:
self.request = kwargs['instance']
super(PhoneForm, self).__init__(*args, **kwargs)
#self.fields['user'].widget.attrs['readonly'] = True
self.fields['primary'].help_text = _('<strong>Check:</strong> If this is your main contact phone number.')
def clean(self):
cleaned_data = super(PhoneForm, self).clean()
customUser = self.request.session['user_id']
phone_name = cleaned_data.get('phone_name')
country = cleaned_data.get('country')
phone_number = cleaned_data.get('phone_number')
phone_type = cleaned_data.get('phone_type')
primary = cleaned_data.get('primary')
try:
del self.request.session['validation_error']
except KeyError:
pass
if "action_add" in self.request.POST:
try:
phonenum = Phone.objects.filter(customUser=customUser, country=country, phone_number=phone_number).first()
if phonenum:
#messages.error(self.request, _('This Phone is registered already.'))
raise forms.ValidationError(_('This Phone is registered already.'))
except Phone.DoesNotExist:
pass
try:
phone = Phone.objects.filter(customUser=customUser, primary=True).first()
if phone and primary:
#messages.error(self.request, _('There is another "Primary" Phone already.'))
raise forms.ValidationError(_('There is another "Primary" Phone #already.'), code='invalid')
except Phone.DoesNotExist:
pass
if "action_update" in self.request.POST:
if "country" in self.changed_data or "phone_number" in self.changed_data:
raise forms.ValidationError(_('You can´t update the Country nor the Phone number of the existing Phone.'))
try:
phone = Phone.objects.filter(customUser=customUser, primary=True).first()
if phone and primary and self.request.session['Phone_object_id'] != phone.id:
raise forms.ValidationError(_('There is another "Primary" Phone #already.'), code='invalid')
except Phone.DoesNotExist:
pass
if not phone_name and not phone_type and not phone_number:
raise forms.ValidationError(_('You have to fill out the form!'))
return cleaned_data
我在视图中的新 get_context_data 方法是:
def get_context_data(self, **kwargs):
#Use this to add extra context.#
context = super(PhoneCreateView, self).get_context_data(**kwargs)
form = self.form_class(instance=self.object)
form.instance.customUser = CustomUser.objects.get(id=self.request.user.id)
self.request.session['user_id'] = self.request.user.id
return context
我有一个表单和一个 CBV CreateView。我需要将 request.user 分配给用户字段(CustomUser 模型的外键),它在表单中是一个隐藏字段(用户)。但是,我尝试使用 "self.fields['user'] = self.request.user.id" 形式的 init 方法,但出现错误:'NoneType' 对象没有属性 'user'。实现此目标的最简洁方法是什么?
我尝试了很多不同的方法,但都没有成功。 ):
这是我的表格:
class PhoneForm(forms.ModelForm):
class Meta:
model = Phone
fields = 'user', 'phone_name', 'country', 'phone_number', 'phone_type', 'primary'
widgets = {'user': forms.HiddenInput()}
def __init__(self, *args, **kwargs):
self.request = kwargs.pop('request', None)
super(PhoneForm, self).__init__(*args, **kwargs)
self.fields['user'].widget.attrs['readonly'] = True
self.fields['user'] = self.request.user.id
self.fields['primary'].help_text = _('<strong>Check:</strong> If this is your main contact phone number.')
def clean(self):
cleaned_data = super(PhoneForm, self).clean()
user = cleaned_data.get('user')
phone_name = cleaned_data.get('phone_name')
country = cleaned_data.get('country')
phone_number = cleaned_data.get('phone_number')
phone_type = cleaned_data.get('phone_type')
primary = cleaned_data.get('primary')
print('user: ',user)
print('phone_name: ',phone_name)
print('country: ',country)
print('phone_number: ',phone_number)
print('phoe_type: ',phone_type)
print('primary: ',primary)
if "action_add" in self.request.POST:
try:
phonenum = Phone.objects.filter(user=user, country=country, phone_number=phone_number).first()
if phonenum:
raise forms.ValidationError(_('This Phone is registered already.'))
except Phone.DoesNotExist:
pass
try:
phone = Phone.objects.filter(user=user, primary=True).first()
if phone and primary:
raise forms.ValidationError(_('There is another "Primary" Phone #already.'), code='invalid')
except Phone.DoesNotExist:
pass
if "action_update" in self.request.POST:
if "country" in self.changed_data or "phone_number" in self.changed_data:
raise forms.ValidationError(_('You can´t update the Country nor the Phone number of the existing Phone.'))
try:
phone = Phone.objects.filter(user=user, primary=True).first()
if phone and primary and self.request.session['Phone_object_id'] != phone.id:
raise forms.ValidationError(_('There is another "Primary" Phone #already.'), code='invalid')
except Phone.DoesNotExist:
pass
if not phone_name and not phone_type and not phone_number:
raise forms.ValidationError(_('You have to fill out the form!'))
这是我的观点:
class PhoneCreateView(LoginRequiredMixin, CreateView):
form_class = PhoneForm
model = Phone
template_name = 'phones/addPhone.html'
login_url = reverse_lazy('account_login')
success_url = reverse_lazy('phonesList')
class Meta:
readonly = ('user', )
def get_form_kwargs(self):
kw = super(PhoneCreateView, self).get_form_kwargs()
kw['request'] = self.request
return kw
def get_initial(self):
phone = Phone.create(self.request.user.id)
form = self.form_class(instance=phone)
form.instance.user = CustomUser.objects.get(id=self.request.user.id)
return {'form': form, }
def get_context_data(self, **kwargs):
context = super(PhoneCreateView, self).get_context_data(**kwargs)
form = self.form_class(instance=self.object)
form.instance.user = CustomUser.objects.get(id=self.request.user.id)
context = {
'form': form,
'user': self.request.user.id,
}
return context
def form_valid(self, form):
form.instance.user = CustomUser.objects.get(id=self.request.user.id)
form.instance.status = 'A'
form.instance.status_dt = timezone.now()
form.instance.at_user = self.request.user.email
form.instance.at_ip = visitor_ip_address(self.request)
form.instance.at_dttm = timezone.now()
form.instance.at_action = 'Create Phone number'
messages.success(self.request, _('Your Phone Number has been registered.'))
return super(PhoneCreateView, self).form_valid(form)
这是我的模型:
class Phone(models.Model):
PHONETYPES = (
('1', _('Mobile')),
('2', _('Home')),
('3', _('Work')),
('4', _('Other')),
)
status = models.CharField(_("Record Status"), max_length=1, default='A')
status_dt = models.DateTimeField(_("Status Date"), default=timezone.now)
user = models.ForeignKey(CustomUser, verbose_name=_("User"), on_delete=models.CASCADE)
phone_name = models.CharField(_("Phone name"), max_length=20, default="PH"+str(random.randint(1,99999)))
country = models.IntegerField(_("Country Dialing Code"))
phone_number = models.CharField(_("Phone Number"), max_length=11)
phone_type = models.CharField(_("Phone Type"), max_length=1, default="4", choices=PHONETYPES)
verified = models.BooleanField(verbose_name=_('verified'), default=False)
primary = models.BooleanField(verbose_name=_('primary'), default=False)
at_user = models.CharField(_("Audit Trail (user)"), max_length=255, blank=True)
at_ip = models.GenericIPAddressField(_("Audit Trail (IP)"), protocol='both', blank=True, null=True)
at_dttm = models.DateTimeField(_("Audit Trail (Date-Time)"), default=timezone.now)
at_action = models.CharField(_("Audit Trail (Function performed)"), max_length=255, blank=True)
UniqueConstraint(fields=['user', 'country', 'phone_number'], name='user_unique_phone_number')
class Meta:
verbose_name = _("Phone Number")
verbose_name_plural = _("Phone Numbers")
@classmethod
def create(cls, user):
phone = cls(user= get_object_or_404(CustomUser, pk=user))
# phone create
return phone
def __str__(self):
return self.phone_name
我不得不改变一些东西。首先从表单和字段中取出隐藏字段用户(这是用户 table 的外键)。相反,我使用了一个会话参数来存储用户 ID。然后我不得不在视图中重新表述我的方法 get_context_data。以下是更新后的代码:
我的新表格:
class PhoneForm(forms.ModelForm):
class Meta:
model = Phone
fields = 'phone_name', 'country', 'phone_number', 'phone_type', 'primary'
#widgets = {'user': forms.HiddenInput()}
def __init__(self, *args, **kwargs):
self.request = kwargs.pop('request', None)
if self.request is None:
self.request = kwargs['instance']
super(PhoneForm, self).__init__(*args, **kwargs)
#self.fields['user'].widget.attrs['readonly'] = True
self.fields['primary'].help_text = _('<strong>Check:</strong> If this is your main contact phone number.')
def clean(self):
cleaned_data = super(PhoneForm, self).clean()
customUser = self.request.session['user_id']
phone_name = cleaned_data.get('phone_name')
country = cleaned_data.get('country')
phone_number = cleaned_data.get('phone_number')
phone_type = cleaned_data.get('phone_type')
primary = cleaned_data.get('primary')
try:
del self.request.session['validation_error']
except KeyError:
pass
if "action_add" in self.request.POST:
try:
phonenum = Phone.objects.filter(customUser=customUser, country=country, phone_number=phone_number).first()
if phonenum:
#messages.error(self.request, _('This Phone is registered already.'))
raise forms.ValidationError(_('This Phone is registered already.'))
except Phone.DoesNotExist:
pass
try:
phone = Phone.objects.filter(customUser=customUser, primary=True).first()
if phone and primary:
#messages.error(self.request, _('There is another "Primary" Phone already.'))
raise forms.ValidationError(_('There is another "Primary" Phone #already.'), code='invalid')
except Phone.DoesNotExist:
pass
if "action_update" in self.request.POST:
if "country" in self.changed_data or "phone_number" in self.changed_data:
raise forms.ValidationError(_('You can´t update the Country nor the Phone number of the existing Phone.'))
try:
phone = Phone.objects.filter(customUser=customUser, primary=True).first()
if phone and primary and self.request.session['Phone_object_id'] != phone.id:
raise forms.ValidationError(_('There is another "Primary" Phone #already.'), code='invalid')
except Phone.DoesNotExist:
pass
if not phone_name and not phone_type and not phone_number:
raise forms.ValidationError(_('You have to fill out the form!'))
return cleaned_data
我在视图中的新 get_context_data 方法是:
def get_context_data(self, **kwargs):
#Use this to add extra context.#
context = super(PhoneCreateView, self).get_context_data(**kwargs)
form = self.form_class(instance=self.object)
form.instance.customUser = CustomUser.objects.get(id=self.request.user.id)
self.request.session['user_id'] = self.request.user.id
return context