如何通过Django实现餐厅注册时的营业时间录入功能
Hey there! Let's work through finishing the business hours entry feature for your restaurant delivery platform. Based on the code snippet you shared, here's a practical step-by-step guide to get this up and running:
First, let's fix and structure your models properly. Since a single restaurant will have multiple business hours (one per weekday), we'll create a dedicated BusinessHours model linked to your Restaurant model. This avoids repeating data and keeps things organized:
from django.db import models from django.utils.translation import gettext_lazy as _ from django.core.exceptions import ValidationError WEEKDAYS = [ (1, _("Monday")), (2, _("Tuesday")), (3, _("Wednesday")), (4, _("Thursday")), (5, _("Friday")), (6, _("Saturday")), (7, _("Sunday")), ] class Restaurant(models.Model): # Add your core restaurant fields here (name, address, contact, etc.) name = models.CharField(max_length=255, verbose_name=_("Restaurant Name")) address = models.TextField(verbose_name=_("Address")) # ... other fields relevant to your platform class BusinessHours(models.Model): restaurant = models.ForeignKey( Restaurant, on_delete=models.CASCADE, related_name="business_hours", verbose_name=_("Restaurant") ) weekday = models.IntegerField(choices=WEEKDAYS, verbose_name=_("Weekday")) from_hour = models.TimeField(verbose_name=_("Opening Time")) to_hour = models.TimeField(verbose_name=_("Closing Time")) class Meta: # Ensure one business hour entry per weekday per restaurant unique_together = ('restaurant', 'weekday') verbose_name_plural = _("Business Hours") def clean(self): # Add validation to ensure closing time is after opening time if self.from_hour >= self.to_hour: raise ValidationError(_("Closing time must be later than opening time.")) super().clean()
To let merchants input business hours during registration, we'll use Django's inlineformset_factory—this lets you add multiple BusinessHours entries directly on the same form as the restaurant registration:
from django import forms from .models import Restaurant, BusinessHours class RestaurantForm(forms.ModelForm): class Meta: model = Restaurant fields = ['name', 'address'] # Include all your restaurant fields here # Create a formset for business hours BusinessHoursFormSet = forms.inlineformset_factory( Restaurant, BusinessHours, fields=['weekday', 'from_hour', 'to_hour'], extra=7, # Show all 7 weekdays by default can_delete=False, # Disable deletion during initial registration (enable later for edits) widgets={ # Optional: Use time picker widgets for better UX 'from_hour': forms.TimeInput(attrs={'type': 'time'}), 'to_hour': forms.TimeInput(attrs={'type': 'time'}), } )
Now, modify your view to handle both the restaurant form and the business hours formset, ensuring both are validated and saved together:
from django.shortcuts import render, redirect from .forms import RestaurantForm, BusinessHoursFormSet def restaurant_register(request): if request.method == 'POST': restaurant_form = RestaurantForm(request.POST) # Link the formset to the restaurant form's instance hours_formset = BusinessHoursFormSet(request.POST, instance=restaurant_form.instance) if restaurant_form.is_valid() and hours_formset.is_valid(): # Save the restaurant first, then the hours restaurant = restaurant_form.save() hours_formset.save() # Redirect to your merchant dashboard or success page return redirect('merchant_dashboard') else: # Initialize empty forms for GET requests restaurant_form = RestaurantForm() hours_formset = BusinessHoursFormSet() context = { 'restaurant_form': restaurant_form, 'hours_formset': hours_formset } return render(request, 'restaurant/register.html', context)
Finally, build the template to display both forms. Make sure to include the formset's management_form—this is required for Django to process the formset correctly:
{% extends 'base.html' %} {% load i18n %} {% block content %} <h2>{% trans "Register Your Restaurant" %}</h2> <form method="post" class="restaurant-registration-form"> {% csrf_token %} <!-- Restaurant Details Form --> <div class="form-section"> <h3>{% trans "Restaurant Information" %}</h3> {{ restaurant_form.as_p }} </div> <!-- Business Hours Formset --> <div class="form-section"> <h3>{% trans "Business Hours" %}</h3> {{ hours_formset.management_form }} {% for form in hours_formset %} <div class="business-hour-row"> {{ form.weekday.label_tag }} {{ form.weekday }} {{ form.from_hour.label_tag }} {{ form.from_hour }} {{ form.to_hour.label_tag }} {{ form.to_hour }} {% if form.errors %} <div class="error-message"> {% for field, errors in form.errors.items %} {% for error in errors %} {{ error }} {% endfor %} {% endfor %} </div> {% endif %} </div> {% endfor %} </div> <button type="submit" class="submit-btn">{% trans "Complete Registration" %}</button> </form> {% endblock %}
- Add CSS styling to group each weekday's time inputs together for clarity.
- Pre-select the weekday choices so merchants don't have to pick each one manually (since we set
extra=7, each form will correspond to a unique weekday—you can set initial values in the formset if needed). - For restaurants with the same hours every day, add a "Copy to All" button using JavaScript to save merchants time.
内容的提问来源于stack exchange,提问作者Doing Things Occasionally

