models.py에 Passenger을 작성하고 migrate한다.
class Passenger(models.Model):
first = models.CharField(max_length=64)
last = models.CharField(max_length=64)
flights = models.ManyToManyField(Flight, blank=True, related_name="passengers")
def __str__(self):
return f"{self.first} {self.last}"
python manage.py makemigrations
python manage.py migrate
admin.py에 Passenger을 추가하고 admin page에 들어가보면
Flights를 복수 선택할 수 있다.
views.py의 flight 메소드에 passengers를 추가하고
def flight(request, flight_id):
flight = Flight.objects.get(pk=flight_id)
return render(request, "flights/flight.html", {
"flight": flight,
"passengers": flight.passengers.all()
})
flight.html에 passenger 부분을 추가하면
<h2>Passengers</h2>
<ul>
{% for passenger in passengers %}
<li>{{ passenger }}</li>
{% empty %}
<li>No passengers.</li>
{% endfor %}
</ul>
/flights/1으로 가면 1번 flight에 해당하는 passenger를 볼 수 있다.
urls.py
path("<int:flight_id>/book", views.book, name="book")
views.py
def flight(request, flight_id):
flight = Flight.objects.get(pk=flight_id)
return render(request, "flights/flight.html", {
"flight": flight,
"passengers": flight.passengers.all(),
"non_passengers":Passenger.objects.exclude(flights=flight).all()
})
def book(request, flight_id):
if request.method == "POST":
flight = Flight.objects.get(pk=flight_id)
passenger = Passenger.objects.get(pk=int(request.POST["passenger"]))
passenger.flights.add(flight)
return HttpResponseRedirect(reverse("flight", args=(flight.id,)))
flight.html
<h2>Add Passenger</h2>
<form action="{% url 'book' flight.id %}" method="post">
{% csrf_token %}
<select name="passenger">
{% for passenger in non_passengers %}
<option value="{{ passenger.id }}">{{ passenger }}</option>
{% endfor %}
</select>
<input type="submit">
</form>
<form>
tag학습 후기
백엔드만 했을 때는 html render를 신경쓰지 않고, data 저장 및 전달을 했었는데 너무 헷갈린다.