While adding a book, I have to get data from frontend. I created a AddBookForm
form. Book
and Author
have Many-to-Many relationship. From the frontend Form
I get the names of the authors for the corresponding book as a list(from dynamic input field). Now the data is saved but is stored incorrectly. I know this is not the optimized way to save many to many relationship data. Please help me do this in an optimized way.
models.py:
class Book(models.Model):
name = models.CharField(max_length=200, null=False, blank=False)
description = models.TextField(null=True, blank=True)
no_of_copies = models.IntegerField(default=1, null=True, blank=True)
status = models.CharField(max_length=15, choices=[('Out of Stock', 'Out of Stock'), ('Available', 'Available')], default='Available')
updated_at = models.DateTimeField(auto_now=True)
created_at = models.DateTimeField(auto_now=True)
def __str__(self):
return self.name
class Author(models.Model):
name = models.CharField(max_length=100, null=True, blank=True)
books = models.ManyToManyField(Book)
def __str__(self):
return self.name
class Genre(models.Model):
name = models.CharField(max_length=50, null=True, blank=True)
books = models.ManyToManyField(Book)
def __str__(self):
return self.name
forms.py
class AddBookForm(forms.ModelForm):
authors = forms.CharField(max_length=255, required=False)
genres = forms.CharField(max_length=255, required=False)
class Meta:
model = Book
fields = '__all__'
views.py
def add_book(request):
if request.method == 'POST':
form = AddBookForm(request.POST)
if form.is_valid():
book = form.save(commit=False)
authors = request.POST.getlist('authors')
book.save()
for name in authors:
author, created = Author.objects.get_or_create(name=name)
author.books.add(book)
return redirect("/")
else:
form = AddBookForm()
context = {'form': form}
return render(request, 'book/add_book.html', context)
I want to add the authors corresponding to that books to the database. I found out that .set()
can be used but I am not sure how to use this in this context. Could you please mention if it is possible to do this with .set()
And also should I create another ManyToManyField
in the Book
model?
Kindly help me with this problem. Thank you
hello my friend first of all you just need to override the save in your form:
so it will be like this:
def save(self, commit=True):
book = super().save(commit=False) # get the instance
if commit:
book.save()# normally save the book
authors = self.cleaned_data.get('authors') # get the authors (ids also valid)
if authors:
book.authors_set.set(authors) # set the authors to the book
return book