Home > Blockchain >  Child form instance in Django
Child form instance in Django

Time:02-02

As a beginner in a contact list project I could not pass the instance of the contact profiles to the phone list form. When I want to add several phone numbers to a person I need the person's instance to be loaded to the add-phone form. when I call the function 'addphone' the form opens a new phone for a list of contacts.

models.py

class contact_names(models.Model):
    first_name=models.CharField(max_length=20,null=True,blank=True)
    last_name=models.CharField(max_length=20)
    area_l=(
        ('TWO','TWO'),
        .
        .
    )
    dep_l=(
        .
        .
        ('Other','Other'),
    )
    area=models.CharField(max_length=22,choices=area_l,null=True,blank=True)
    DEP =models.CharField(max_length=22, blank=True, null=True, choices=dep_l)
    Subdivision =models.CharField(max_length=20, blank=True, null=True)
    created=models.DateTimeField(auto_now_add=True)
    id=models.UUIDField(default=uuid.uuid4, unique=True,editable=False,primary_key=True)

    def __str__(self) -> str:
        return self.last_name
    def __str__(self) -> str:
        return self.first_name
    

class contact_phone(models.Model):
    p_type=(
        ('Fixed Phone','Fixed Phone'),
         ('Cell Phone','Cell Phone'),
    )
    typep=models.CharField(max_length=15, choices=p_type)
    person=models.ForeignKey(contact_names, on_delete=models.CASCADE)
    phone=models.CharField(max_length=15)
    def __str__(self) -> str:
        return self.phone

views.py

def user(request):
    form=newuser()
    if request.method =='POST':
        form=newuser(request.POST)
        if form.is_valid():
            form.save(commit=True)
            return redirect('contacts')
    return render(request,'apptwo/form_page.html',{'form':form})

def addphone(request,pk):
    ps=contact_names.objects.get(id=pk)
    form=newphone(instance=ps)
    if request.method =='POST':
        form=newphone(request.POST)
        if form.is_valid():
            form.save(commit=True)
            return redirect('contacts')
    return render(request,'apptwo/form_page2.html',{'form':form})

forms.py

class newuser(forms.ModelForm):
    class Meta:
        model= contact_names
       
        fields='__all__'
        
class newphone(forms.ModelForm):
    class Meta:
        model=contact_phone
        fields=['person','typep','phone']

CodePudding user response:

It looks like you're trying to create a phone number form that is associated with a specific contact profile. In your addphone view, you are correctly fetching the contact profile from the database using the primary key (pk) passed in through the URL, but in the POST portion of the view, you are creating a new form without passing in the instance of the contact profile that you fetched earlier.

To fix this, you should update the POST portion of the addphone view to use the instance of the contact profile when creating the phone number form:

if request.method =='POST':
form=newphone(request.POST,instance=ps)
if form.is_valid():
    form.save(commit=True)
    return redirect('contacts')

Also, In your form, you should define the foreign key to person and it should be hidden in the form,

class newphone(forms.ModelForm):
person = forms.ModelChoiceField(queryset=contact_names.objects.all(), widget=forms.HiddenInput())
class Meta:
    model=contact_phone
    fields=['person','typep','phone']

This way when you save the form, the person foreign key will be automatically set to the instance of the contact you passed.

CodePudding user response:

I have found a way but with minor issues. Still when I want to add the first phone to the particular person, the person dropdown list is shown as '------', in form as default, but the instance is OK. And when I want to add a new second phone, the phone field in the form is not empty. I'll be very glad if someone helps me. I appreciate the posted answer, it helped but didn't solve it completely.

views.py

def addphone(request,pk):
ps=contact_names.objects.filter(id=pk)
for s in ps:
    pd=s.contact_phone_set.all()
    
if pd.first()== None:
    form=newphone(instance=s)
    form.fields['person'].queryset=ps
else:
    form=newphone(instance=pd.last())
    form.fields['phone'].queryset=None # <------This has no effect!

if request.method =='POST':
    form=newphone(request.POST)
    if form.is_valid():
        form.save(commit=True)
        return redirect('contacts')
return render(request,'apptwo/form_page2.html',{'form':form})enter code here

forms.py

class newphone(forms.ModelForm):
# person = forms.ModelChoiceField(queryset=contact_names.objects.all(), widget=forms.HiddenInput())# #THis didn't Help Since the field is required. 
class Meta:
    model=contact_phone
    p_type=(
    ('Fixed Phone','Fixed Phone'),
     ('Cell Phone','Cell Phone'),)

    fields=['person','typep','phone']
    labels = {
        'typep': '',
    }
    widgets = {
        'typep': forms.RadioSelect(choices=p_type)
    }
  • Related