【问题标题】:Django form and CBV CreateView not able to assign request.user to user fieldDjango 表单和 CBV CreateView 无法将 request.user 分配给用户字段
【发布时间】:2020-04-22 15:44:25
【问题描述】:

我有一个表单和一个 CBV CreateView。我需要将 request.user 分配给用户字段(CustomUser 模型的外键),该字段在表单中是一个隐藏字段(用户)。但是,我通过“self.fields['user'] = self.request.user.id”尝试了 init 形式的方法,我得到了错误:'NoneType' object has no attribute'用户'。实现这一目标的最干净的方法是什么?

我尝试了许多不同的方法,但都没有成功。 ):

这是我的表格:

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

【问题讨论】:

    标签: django django-forms django-class-based-views


    【解决方案1】:

    我不得不改变一些事情。首先从表单和字段中取出隐藏字段用户(它是用户表的外键)。相反,我使用了一个会话参数来存储用户 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
    
    

    【讨论】:

      猜你喜欢
      • 2011-10-16
      • 2020-02-01
      • 2014-04-09
      • 2017-05-04
      • 2017-08-31
      • 2019-09-29
      • 2018-03-04
      • 1970-01-01
      • 2020-05-08
      相关资源
      最近更新 更多