djangoactivity-oncreateview

django createviw- create another model object and use it in current model


I have two models as given below.

class Account(models.Model):

   ASSET='A'
   LIABILITY='L'
   INCOME='I'
   EXPENSE='E'
   ACCOUNT_TYPE=((ASSET,'Asset'),
        (LIABILITY,'Liability'),
        (INCOME,'Income'),
        (EXPENSE,'Expense'))
   name=models.CharField(unique=True,db_index=True,max_length=70)
   type=models.CharField(choices=ACCOUNT_TYPE,max_length=1)

class Person(models.Model):
    first_name=models.CharField(max_length=30,)
    last_name=models.CharField(max_length=30,)
    account=models.OneToOneField(Account,on_delete=models.CASCADE)

The Person model has the following CreateView and a model form.

class CreatePerson(CreateView):
    model=Person
    form_class=CreatePersonForm

class CreatePersonForm(forms.ModelForm):
    display_name=forms.CharField()

    class Meta:
        model= Person
        fields = ['first_name','last_name','display_name']

When creating a new Person, I need to

  1. create an Account object first (with name=display_name, type='A') and need to assign it to the Person object.

  2. render the form again if the Account with same display_name already exists, with a validation error.

Could someone please point the right direction to proceed here?

Thanks.


Solution

  • You can implement clean_display_name method to check if Acount already exists:

    class CreatePersonForm(forms.ModelForm):
        display_name=forms.CharField()
    
        class Meta:
            model= Person
            fields = ['first_name','last_name','display_name']
    
        def clean_display_name(self):
            name = self.cleaned_data.get('display_name')
            account = Account.objects.filter(name=name).exists() 
            if account:
                raise forms.ValidationError('Account already exists')
            return name
    

    To add account to profile you can override view's form_valid method:

    class CreatePerson(CreateView):
        model=Person
        form_class=CreatePersonForm
    
        def form_valid(self, form):
            account = Account.objects.create(name=form.cleaned_data['display_name'])
            form.instance.account = account
            return super().form_valid(form)