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?
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].