pythondjangodjango-modelsdjango-formsdjango-widget

How to 'check' a value in a radio button by default in Django?


I wrote a model form. I used widgets to make radio buttons and I want a particular radio button to be checked by default while rendering the form in my html file.

Model:

class Room(models.Model):
    class Meta:
    number =  models.PositiveSmallIntegerField()
    CATEGORIES = (
        ('Regular', 'Regular'),
        ('Executive', 'Executive'),
        ('Deluxe', 'Deluxe'),
    )
    category = models.CharField(max_length=9, choices=CATEGORIES, default='Regular')
    CAPACITY = (
        (1, '1'),
        (2, '2'),
        (3, '3'),
        (4, '4'),
    )
    capacity = models.PositiveSmallIntegerField(
        choices=CAPACITY, default=2
        )
    advance = models.PositiveSmallIntegerField(default=10)
    manager = models.CharField(max_length=30)

The following is my model form based on the above model.

Form:

class AddRoomForm(forms.ModelForm):
    ROOM_CATEGORIES = (
        ('Regular', 'Regular'),
        ('Executive', 'Executive'),
        ('Deluxe', 'Deluxe'),
    )

    category = forms.CharField(
        max_length=9,
        widget=forms.RadioSelect(choices=ROOM_CATEGORIES),
    )

    ROOM_CAPACITY = (
        (1, '1'),
        (2, '2'),
        (3, '3'),
        (4, '4'),
    )

    capacity = forms.CharField(
        max_length=9,
        widget=forms.RadioSelect(choices=ROOM_CAPACITY),
    )
    class Meta:
        model = Room
        fields = ['number', 'category', 'capacity', 'advance']

Here is the views:

def add_room(request):
    if request. Method == 'POST':
        form = AddRoomForm(request.POST)
        if form.is_valid():
            room = Room(number=request.POST['number'],
                    category=request.POST['category'],
                    capacity=request.POST['capacity'],
                    advance=request.POST['advance'],
                    manager=request.user.username)
            room.save()
            # Implemented Post/Redirect/Get.
            return redirect('../rooms/')
        else:
            context = {
                'form': form,
                'username': request.user.username
                }
            return render(request, 'add_room.html', context)
    context = {
            'form': AddRoomForm(),
            'username': request.user.username
            }
    return render(request, 'add_room.html', context)

I rendered the form like this in my html file.

<form method="POST">
  {% csrf_token %}
  {{ form.as_p }}
  <input type="submit" class= "submit submit-right" value="Add" />
</form>

I read somewhere that I can use 'initial' keyword in my views.py file but I don't understand how can I use it. Can someone please help me with it?


Solution

  • By overriding the field, you lose the binding with the underlying model field. Just specify the widget:

    class AddRoomForm(forms.ModelForm):
        class Meta:
            model = Room
            fields = ['number', 'category', 'capacity', 'advance']
            widgets = {'category': forms.RadioSelect, 'capacity': forms.RadioSelect}

    It is probably also better to work with a ForeignKey to the user model for the manager:

    from django.conf import settings
    
    
    class Room(models.Model):
        number = models.PositiveSmallIntegerField()
        CATEGORIES = (
            ('Regular', 'Regular'),
            ('Executive', 'Executive'),
            ('Deluxe', 'Deluxe'),
        )
        category = models.CharField(
            max_length=9, choices=CATEGORIES, default='Regular'
        )
        CAPACITY = (
            (1, '1'),
            (2, '2'),
            (3, '3'),
            (4, '4'),
        )
        capacity = models.PositiveSmallIntegerField(choices=CAPACITY, default=2)
        advance = models.PositiveSmallIntegerField(default=10)
        manager = models.ForeignKey(
            settings.AUTH_USER_MODEL, on_delete=models.CASCADE, editable=False
        )

    and the ModelForm can handle the creation itself:

    from django.contrib.auth.decorators import login_required
    
    
    @login_required
    def add_room(request):
        if request.method == 'POST':
            form = AddRoomForm(request.POST, request.FILES)
            if form.is_valid():
                form.instance.manager = request.user
                form.save()
                return redirect('../rooms/')
        else:
            form = AddRoomForm()
        context = {'form': form, 'username': request.user.username}
        return render(request, 'add_room.html', context)

    Note: You can limit views to a view to authenticated users with the @login_required decorator [Django-doc].