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.