forms for adding or selecting records
Date: March 26th 2016
Last updated: March 26th 2016
Adding and selecting records to associate with an existing user seems to be similar tasks. However, my solution for each task is different. In this example I have two models: surfboards (called Board) and Surfer. These two tables have a ManyToMany relationship.
The objective is to allow a surfer to add a board to the database which gets automatically selected for them. Then, any surfer can select many boards regardless of who added it to the database. Here is my solution to adding and selecting records.
models.py
This code has been snipped to remove fields and functions that are not the point of this example.
class Board(models.Model):
# <- snipped ->
boardshaper = models.CharField('Shaper', max_length=40, null=True, blank=True)
class Meta:
unique_together = (('boardtail','boardlength','boardmake','boardwidth'))
class Surfer(models.Model):
user = models.OneToOneField(User)
#<- snipped ->
boards = models.ManyToManyField(Board) #<======== ManyToMany relationship
profile.html
<h3> Quiver <a href="{% url 'surferprofile:addboard' surfer.id %}"
style="color: grey; font-size: small; text-decoration: none;">
add board </a></h3>
<p><a href="{% url 'surferprofile:selectboard' surfer.id %}"
style="color: blue; text-decoration: none;"> select </a></p>
urls.py
When add board or select is clicked a command is sent to urls.py and the appropriate view is called.
from django.conf.urls import url
from . import views
app_name = 'surferprofile'
urlpatterns = [
#<- snipped ->
url(r'^(?P<surfer_id>[0-9]+)/boards/$', views.addboard, name='addboard'),
url(r'^(?P<surfer_id>[0-9]+)/selectboard/$', views.selectboard, name='selectboard'),
]
views.py
Note that the addboard view is assigning the board to the surfer creating the object. A major difference occurs in forms.py (There is a big difference in BoardForm and BoardSelectForm).
@login_required
def addboard(request, surfer_id):
""" Add a board to the website and associate with current profile """
surfer = get_object_or_404(Surfer, pk=surfer_id)
if request.method == "POST":
form = BoardForm(request.POST)
if form.is_valid():
board = form.save()
surfer.boards.add(board) #<===== assign to surfer creating the board
surfer.save() # refer to django/update_another_table_via_form.html
return redirect('/{}/'.format(surfer_id))
else:
form = BoardForm()
return render(request, 'surferprofile/addboard.html',
{'surfer': surfer, 'form': form})
@login_required
def selectboard(request, surfer_id):
""" select all the boards associated with one surfer """
surfer = get_object_or_404(Surfer, pk=surfer_id)
form = BoardSelectForm(request.POST or None, instance=surfer)
if form.is_valid():
form.save()
return redirect('/{}/'.format(surfer_id))
return render(request, 'surferprofile/selectboard.html',
{'surfer': surfer, 'form': form})
forms.py
The BoardForm calls up the Board model, while the BoardSelectForm calls up the Surfer model. For the BoardSelectForm I am using a queryset to provide a selectable field showing all the boards added to the database.
class BoardForm(forms.ModelForm):
class Meta:
model = Board
fields = ['boardtail','boardlength', 'boardwidth',
'boardthickness','boardvolume', 'boardrocker',
'boardmake', 'boardshaper']
class BoardSelectForm(forms.ModelForm):
boards = forms.ModelMultipleChoiceField(
queryset=Board.objects.all())
class Meta:
model = Surfer
fields = ['boards']
BoardForm
BoardSelectForm
The new board was automatically added to the boards associated with this surfer. Shown below with two rows highlighted (AnotherTest and HugeBoard designs).