You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Django公寓预订系统开发咨询:模型设计与关联方法

Step-by-Step Guide to Build a Booking System for Your Django Apartment Site

Hey there! Since you already have your Apartment model and Django's built-in auth system up and running, let's break down how to add the booking feature step by step. I'll keep things clear and beginner-friendly so you can follow along easily.


1. Finalize Your Booking Model

First, let's make sure your Booking model is set up correctly to link users, apartments, and booking dates. Add this to your app's models.py:

from django.db import models
from django.contrib.auth.models import User
from .models import Apartment  # Import your existing Apartment model
from django.utils import timezone

class Booking(models.Model):
    # Link to the logged-in user
    user = models.ForeignKey(User, on_delete=models.CASCADE, related_name="bookings")
    # Link to the apartment being booked
    apartment = models.ForeignKey(Apartment, on_delete=models.CASCADE, related_name="bookings")
    # Booking dates
    start_date = models.DateField()
    end_date = models.DateField()
    # Optional: Track booking status (e.g., confirmed, pending)
    STATUS_CHOICES = [
        ('P', 'Pending'),
        ('C', 'Confirmed'),
        ('CXL', 'Cancelled'),
    ]
    status = models.CharField(max_length=3, choices=STATUS_CHOICES, default='P')
    # Auto-set when the booking is created
    created_at = models.DateTimeField(default=timezone.now)

    def __str__(self):
        return f"{self.user.username} - {self.apartment.title} ({self.start_date} to {self.end_date})"

    # Optional: Add validation directly in the model
    def clean(self):
        from django.core.exceptions import ValidationError
        # Ensure start date isn't in the past
        if self.start_date < timezone.now().date():
            raise ValidationError("Start date cannot be in the past.")
        # Ensure end date is after start date
        if self.end_date <= self.start_date:
            raise ValidationError("End date must be after start date.")

Don't forget to run migrations after updating the model:

python manage.py makemigrations
python manage.py migrate

Also, register the Booking model in admin.py so you can manage bookings via the Django admin:

from django.contrib import admin
from .models import Booking

admin.site.register(Booking)

2. Create a Booking Form

Next, we'll build a form for users to enter their desired dates. We'll use ModelForm since most fields (user, apartment) will be set programmatically, not by the user.

Create a forms.py file in your app (if you don't have one already) and add:

from django import forms
from .models import Booking
from django.utils import timezone

class BookingForm(forms.ModelForm):
    class Meta:
        model = Booking
        fields = ['start_date', 'end_date']
        # Add date picker widgets for better UX
        widgets = {
            'start_date': forms.DateInput(attrs={'type': 'date', 'min': timezone.now().date()}),
            'end_date': forms.DateInput(attrs={'type': 'date'}),
        }

    # Add custom validation for dates
    def clean(self):
        cleaned_data = super().clean()
        start_date = cleaned_data.get('start_date')
        end_date = cleaned_data.get('end_date')

        if start_date and end_date:
            if start_date < timezone.now().date():
                self.add_error('start_date', "Start date can't be in the past.")
            if end_date <= start_date:
                self.add_error('end_date', "End date must come after start date.")
        return cleaned_data

3. Build the Booking View

Now, let's create a view that handles the booking request. This view will:

  • Require the user to be logged in
  • Fetch the apartment being booked
  • Validate the form data
  • Check if the apartment is already booked for the selected dates
  • Save the booking if everything checks out

Add this to your app's views.py:

from django.shortcuts import render, get_object_or_404, redirect
from django.contrib.auth.decorators import login_required
from .models import Apartment, Booking
from .forms import BookingForm

@login_required  # Only logged-in users can access this
def book_apartment(request, pk):
    apartment = get_object_or_404(Apartment, pk=pk)

    if request.method == 'POST':
        form = BookingForm(request.POST)
        if form.is_valid():
            booking = form.save(commit=False)
            booking.user = request.user
            booking.apartment = apartment

            # Check for overlapping bookings
            overlapping_bookings = Booking.objects.filter(
                apartment=apartment,
                start_date__lt=booking.end_date,
                end_date__gt=booking.start_date
            ).exists()

            if overlapping_bookings:
                form.add_error(None, "This apartment is already booked for the selected dates.")
            else:
                booking.save()
                # Redirect to a success page or back to the apartment detail
                return redirect('apartment_detail', pk=apartment.pk)  # Replace with your actual detail view name
    else:
        form = BookingForm()

    return render(request, 'book_apartment.html', {'form': form, 'apartment': apartment})

Note: Replace 'apartment_detail' with the actual name of your apartment detail view in the redirect.


4. Update Your URLs

Add a URL pattern for the booking view in your app's urls.py:

from django.urls import path
from . import views

urlpatterns = [
    # Your existing URLs here (e.g., apartment list, detail)
    path('apartment/<int:pk>/book/', views.book_apartment, name='book_apartment'),
]

5. Update Templates

a. Add Booking Button to Apartment Detail Page

In your apartment detail template (e.g., apartment_detail.html), add a booking button/section that only logged-in users can see:

{% if user.is_authenticated %}
    <div class="booking-section">
        <h3>Book This Apartment</h3>
        <a href="{% url 'book_apartment' apartment.pk %}" class="btn btn-primary">Start Booking</a>
    </div>
{% else %}
    <p>Please <a href="{% url 'login' %}">log in</a> to book this apartment.</p>
{% endif %}

b. Create the Booking Form Template

Create a book_apartment.html template to display the booking form and error messages:

{% extends 'base.html' %}  <!-- Use your base template -->

{% block content %}
    <h2>Book {{ apartment.title }}</h2>
    <p>Address: {{ apartment.address }}, {{ apartment.city }}</p>
    <p>Price: ${{ apartment.price }} per night</p>

    <form method="POST">
        {% csrf_token %}
        {{ form.as_p }}
        <button type="submit" class="btn btn-success">Confirm Booking</button>
        <a href="{% url 'apartment_detail' apartment.pk %}" class="btn btn-secondary">Cancel</a>
    </form>

    {% if form.errors %}
        <div class="alert alert-danger mt-3">
            {% for field in form %}
                {% for error in field.errors %}
                    <p>{{ error }}</p>
                {% endfor %}
            {% endfor %}
            {% for error in form.non_field_errors %}
                <p>{{ error }}</p>
            {% endfor %}
        </div>
    {% endif %}
{% endblock %}

6. Test the Flow

Now it's time to test everything out:

  1. Log in as a user
  2. Navigate to an apartment detail page
  3. Click "Start Booking"
  4. Try entering invalid dates (past start date, end date before start date) to see error messages
  5. Try booking dates that overlap with an existing booking to ensure the overlap check works
  6. Confirm a valid booking and check the Django admin to see if it was saved correctly

Optional Enhancements (If You Want to Go Further)

  • Add email notifications to the user and admin when a booking is created
  • Allow users to view and cancel their own bookings (create a "My Bookings" view)
  • Update the Apartment model's in_rent field automatically when a booking is confirmed (use Django signals for this)
  • Add payment integration (more advanced, but possible with services like Stripe)

内容的提问来源于stack exchange,提问作者user12146567

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.14 08:15:50