Reputation: 1954
In a Bookstore application, I have a form to add a Book
written by an Author
and a Shelf
which belongs to a Bookstore
. A book needs to be associated to a Shelf.
class AddBookForm(forms.Form):
def save(self, request):
#Let's say I put an excrutiating number of fields...say 13.
book_name = self.cleaned_data.get('book_name', None)
book_author_pk = self.cleaned_data.get('book_author_pk', None)
book_genre = self.cleaned_data.get('genre', None)
book_price = self.cleaned_data.get('price', None)
book_summary = self.cleaned_data.get('book_summary', None)
bookshop_location = self.cleaned_data.get('bookshop_location', None)
bookshop_shelf_number = self.cleaned_data.get('bookshop_shelf_number', None)
stock = self.cleaned_data.get('stock', None)
promotional_price = self.cleaned_data.get('promotional_price', None)
author_object = Author.objects.get(pk=book_author_pk)
book = Book(
name = book_name,
author = author_object,
genre = genre,
summary = book_summary
)
book.save(force_insert=True)
shelf = Shelf(
bookshop_location = bookshop_location,
shelf_number = bookshop_shelf_number,
stock = stock,
promotional_price = promotional_price
)
shelf.save(force_insert=True, force_update=False)
My question is: Is there actually a more succinct way to write this? I'm pretty sure that there is but I'm missing it somewhere.
Upvotes: 0
Views: 51
Reputation: 25539
If your data is associated with models, it's best to use ModelForm
. You could have as many form as you want in the front end and submit them altogether. The code is really straight forward:
# models.py
class BookForm(forms.ModelForm):
class meta:
model = Book
class Shelf(forms.ModelForm):
class meta:
model = Shelf
# views.py
def addbook(request):
book_form = BookForm(request.POST or None)
shelf_form = SelfForm(request.POST or None)
if book_form.is_valid() and shelf_form.is_valid():
book = book_form.save()
shelf = shelf_form.save()
return redirect('some-list-view')
return render(request,
'addbook.html',
{'book_form': book_form, 'shelf_form': shelf_form})
# addbook.html
<form action="/addbook/" method="post">
{% csrf_token %}
{{ book_form }}
{{ shelf_form }}
<input type="submit" value="Submit" />
</form>
Upvotes: 1
Reputation: 5310
Give this a try
class AddFruitForm(forms.Form):
def save(self, request):
# list all your fields here
fields_expected = ['fruit_name', 'fruit_color', ...]
# this should give you the dict with all the fields equal to "None"
fields = dict.fromkeys(fields_expected)
# this relace the None value with the good data from cleaned_data
fields.update(self.cleaned_data)
# assign all the in the dict to the model, key=value
fruit = Fruit(**fields)
fruit.save(force_insert=True, force_update=False)
However if your model can accept None for those value you shouldn't have to provide to the model explicitly as above, you can do this instead and let the model to handle the default value.
class AddFruitForm(forms.Form):
def save(self, request):
fields = self.cleaned_data
fields['my_custom_field'] = 'some data not from the field'
fruit = Fruit(**fields)
fruit.save(force_insert=True, force_update=False)
Upvotes: 1