Django: Как я могу использовать inlineformset для сохранения нескольких форм, которые имеют один и тот же FK, как и другой объект, создаваемый на той же странице формы?
У меня есть две модели Animal и Gene_Animal_Bridge. У меня есть страница с формой, которая позволяет пользователю добавить новое животное в базу данных и прикрепить все гены, которые у него есть. Гены хранятся в Gene_Animal_Bridge, который содержит FK животного, которому оно принадлежит, и FK гена, который хранится в модели GeneInfo. Все работает нормально, но когда дело доходит до итерации по набору форм, сохраняется только 1 ген, а все остальные формы генов, добавленные на странице, не сохраняются.
Models.py
from django.db import models
import datetime
class Animal(models.Model):
animal_id = models.AutoField(primary_key=True, editable=False, null=False)
gender = models.CharField(max_length=6, choices=(('m','male'), ('f','female')), null=True)
name = models.CharField(max_length=14)
description = models.CharField(max_length=75,blank=True, null=False)
dob = models.DateField(default=datetime.date.today, blank=True, null=True)
purchase_date = models.DateField(default=datetime.date.today, blank=True, null=True)
image = models.ImageField(blank=True, null=True)
prey_type = models.CharField(max_length=20,choices=(('1','2XL Multi'),('2','Large Weaner'),('3','Live Multi'),('4','Small Rat'),('5','Small Weaner')),blank=True, null=True)
last_feed = models.DateField(default=datetime.date.today, blank=True, null=True)
last_shed = models.DateField(default=datetime.date.today, blank=True, null=True)
weight = models.IntegerField(blank=True, null=True)
class GeneInfo(models.Model):
gene_id = models.AutoField(primary_key=True, editable=False, null=False)
gene_name = models.CharField(max_length=20, null=False)
type = models.CharField(max_length=20,choices=(('1','pos het'),('2','het'),('3','visual'),('4','co-dominant'),('5','super'),('6','dominant')),null=False)
def __str__(self):
return (self.gene_name)
class Gene_Animal_Bridge(models.Model):
animal_id = models.ForeignKey(Animal, on_delete=models.CASCADE, related_name="bridge_animal_id", null=True)
gene_id = models.ForeignKey(GeneInfo, on_delete=models.CASCADE, related_name="bridge_gene_id", null=True)
class Breeding(models.Model):
sire_id = models.ForeignKey(Animal, on_delete=models.CASCADE, related_name="breeding_sire_id", null=True)
dame_id = models.ForeignKey(Animal, on_delete=models.CASCADE, related_name="breeding_dame_id", null=True)
date_bred = models.DateField(default=datetime.date.today, blank=True, null=True)
visual_lock = models.CharField(max_length=6, choices=(('y','yes'), ('n','no')), blank=True, null=True)
class Clutch(models.Model):
clutch_id = models.AutoField(primary_key=True, null=False)
sire_id = models.ForeignKey(Animal, on_delete=models.CASCADE, related_name="clutch_sire_id", null=True)
dame_id = models.ForeignKey(Animal, on_delete=models.CASCADE, related_name="clutch_dame_id", null=True)
eggs_num = models.IntegerField(blank=True)
lay_date = models.DateField(default=datetime.date.today, blank=True, null=True)
hatch_date = models.DateField(default=datetime.date.today, blank=True, null=True)
forms.py
from django import forms
from django.forms import ModelForm
from datetime import datetime
from .models import Animal, Gene_Animal_Bridge, GeneInfo
from django.forms import ModelChoiceField
class MyModelChoiceField(ModelChoiceField):
def label_from_instance(self, obj):
return "My Object #%i" % obj.id
class NewAnimal(ModelForm):
class Meta:
model = Animal
exclude = ('image',)
widgets = {
'dob': forms.DateInput(attrs={'type': 'date', 'max': datetime.now().date()}),
'purchase_date': forms.DateInput(attrs={'type': 'date', 'max': datetime.now().date()}),
'last_feed': forms.DateInput(attrs={'type': 'date', 'max': datetime.now().date()}),
'last_shed': forms.DateInput(attrs={'type': 'date', 'max': datetime.now().date()}),
'weight': forms.NumberInput(attrs={'min': 0})
}
class AddGene(ModelForm):
class Meta:
model = Gene_Animal_Bridge
fields = ('gene_id',)
views.py
from django.forms import inlineformset_factory
from django.shortcuts import render, redirect
from django.http import HttpResponseRedirect
from django.urls import reverse
from .forms import AddGene, NewAnimal, GeneInfo
from .models import Animal, Gene_Animal_Bridge
def home(request):
return render(request, 'base/home.html')
def collection(request):
animal_list = Animal.objects.all()
return render(request, 'base/collection.html', {'animal_list':animal_list})
def newanimal(request):
add_gene_formset = inlineformset_factory(Animal,Gene_Animal_Bridge, form=AddGene, extra=1)
animal_form = NewAnimal()
formset = add_gene_formset
if request.method =="POST":
animal_form = NewAnimal(request.POST or None)
formset = add_gene_formset(request.POST or None)
if request.method == "POST":
print(request.POST)
if animal_form.is_valid() and formset.is_valid():
instance = animal_form.save(commit=False)
instance.save()
gene = formset.save(commit=False)
for form in gene:
form.animal_id = instance
form.save()
return redirect(reverse('collection'))
context = {'animal_form': animal_form,'formset': formset}
return render(request, 'base/newanimal.html', context )
P.S. У меня нет большого опыта кодирования, поэтому я не знаком со многими понятиями.