get request data in Django form

前端 未结 4 1409
有刺的猬
有刺的猬 2020-11-28 23:11

Is it possible to get request.user data in a form class? I want to clean an email address to make sure that it\'s unique, but if it\'s the current users email address then

相关标签:
4条回答
  • 2020-11-28 23:17

    Just so you know, with Django 1.4 and generic class based CreateView and UpdateView, a self.instance is populated on each model form, which allows you to compare the POSTed email vs the current user email.

    Here is a code sample, using mixin

    class EmailUniqueMixin(object):
        """
        Ensure each User's email is unique
        on the form level
        """
        def clean_email(self):
            email = self.cleaned_data['email']
            existing_email = User.objects.filter(email=email).exclude(pk=self.instance.id)
            if existing_email:
                raise forms.ValidationError('That email address already exists')
            else:
                return email
    
    0 讨论(0)
  • 2020-11-28 23:22

    Here's the way to get the user in your form when using generic views:

    In the view, pass the request.user to the form using get_form_kwargs:

    class SampleView(View):
        def get_form_kwargs(self):
            kwargs = super(SampleView, self).get_form_kwargs()
            kwargs['user'] = self.request.user
            return kwargs
    

    In the form you will receive the user with the __init__ function:

    class SampleForm(Form):
        def __init__(self, user, *args, **kwargs):
            super(SampleForm, self).__init__(*args, **kwargs)
            self.user = user
    
    0 讨论(0)
  • 2020-11-28 23:31

    Not that I'm aware of. One way to handle this is have your Form class's __init__ take an optional email parameter, which it can store as an attribute. If supplied at form creation time, it can use that during validation for the comparison you're interested in.

    0 讨论(0)
  • 2020-11-28 23:35

    As ars and Diarmuid have pointed out, you can pass request.user into your form, and use it in validating the email. Diarmuid's code, however, is wrong. The code should actually read:

    from django import forms
    
    class UserForm(forms.Form):
        email_address = forms.EmailField(
            widget=forms.TextInput(
                attrs={
                    'class': 'required'
                }
            )
        )
    
        def __init__(self, *args, **kwargs):
            self.user = kwargs.pop('user', None)
            super(UserForm, self).__init__(*args, **kwargs)
    
        def clean_email_address(self):
            email = self.cleaned_data.get('email_address')
    
            if self.user and self.user.email == email:
                return email
    
            if UserProfile.objects.filter(email=email).count():
                raise forms.ValidationError(
                    u'That email address already exists.'
                )
    
            return email
    

    Then, in your view, you can use it like so:

    def someview(request):
        if request.method == 'POST':
            form = UserForm(request.POST, user=request.user)
            if form.is_valid():
                # Do something with the data
                pass
        else:
            form = UserForm(user=request.user)
        # Rest of your view follows
    

    Note that you should pass request.POST as a keyword argument, since your constructor expects 'user' as the first positional argument.

    Doing it this way, you need to pass user as a keyword argument. You can either pass request.POST as a positional argument, or a keyword argument (via data=request.POST).

    0 讨论(0)
提交回复
热议问题