Home > front end >  Cannot assign "": "" must be a '' instance
Cannot assign "": "" must be a '' instance

Time:03-14

I am trying to make a registration key in the UserModel where the key field in the registration form is a foreign key to another model called RegistrationKey. I have made two posts about this topic earlier without any success, however has a few things changed in my code which makes those previous posts irrelevant. In the form field, the field for the key is a CharField as I can not display the keys for the users due to safety.

These are the two previous posts: Save user input which is a string as object in db , Textinput with ModelChoiceField

These are my two models.

class RegistrationKey(models.Model):
    key = models.CharField(max_length=30)

    def __str__(self):
        return self.key


class User(AbstractUser):
    key = models.ForeignKey(RegistrationKey, on_delete=models.CASCADE, null=True, blank=True)

Since my latest posts have I created a class based view, which looks like this:

class RegisterPage(CreateView):
    form_class = MyUserCreationForm


  def form_valid(self, form):
        key = form.cleaned_data['key']
        try:
            keyobject = RegistrationKey.objects.get(key=key)
            form.instance.key = keyobject
            return super().form_valid(form)
        except RegistrationKey.DoesNotExist:
            form.add_error('key', 'error')
            return super().form_invalid(form)

When I try and pass in the value Admin which is an object in the RegistrationKey model I get the following error: 'Cannot assign "'Admin'": "User.key" must be a "RegistrationKey" instance.' I don't know how to solve this, how can this string that the user inputs be assigned to the db?

Edit Here are my form

class MyUserCreationForm(UserCreationForm):
    key = forms.CharField(widget=forms.TextInput(attrs={'class':'form-control', 'placeholder':'Key'}), label='')
    email = forms.EmailField(widget=forms.EmailInput(attrs={'class':'form-control', 'placeholder':'Email'}), label='')



    class Meta:
        model = User
        fields = ('key', 'email', 'password1', 'password2')

    
    def __init__(self, *args, **kwargs):
        super(MyUserCreationForm, self).__init__(*args, **kwargs)

        self.fields['password1'].widget.attrs['class'] = 'form-control'
        self.fields['password1'].widget.attrs['placeholder'] = 'Password'
        self.fields['password1'].label=''

        self.fields['password2'].widget.attrs['class'] = 'form-control'
        self.fields['password2'].widget.attrs['placeholder'] = 'Confirm Password'
        self.fields['password2'].label=''
        
        for fieldname in ['password1', 'password2']:
            self.fields[fieldname].help_text = None

CodePudding user response:

You better move the logic to obtain the item to the form, where it belongs. So with:

from django.core.exceptions import ValidationError

class MyUserCreationForm(UserCreationForm):
    # …

    def clean_key(self):
        key = self.cleaned_data['key']
        try:
            return RegistrationKey.objects.get(key=key)
        except RegistrationKey.DoesNotExist:
            raise ValidationError('The key is not valid.')

That should be sufficient. You should not override the .form_valid(…) method.

  • Related