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).

results matching ""

    No results matching ""