Может ли Django ModelForm сохранять несколько новых моделей при одной отправке?
Я изучаю Django и создаю сайт для сохранения и отображения предложений еды в кафетерии. У меня есть модель Meal и еще один FoodItem, где несколько FoodItem являются дочерними элементами Meal.
class Meal(models.Model):
date = models.DateField(default=datetime.date.today)
BFAST = 0
LUNCH = 1
DIN = 2
MEAL_TIME_CHOICES = [
(BFAST, 'Breakfast'),
(LUNCH, 'Lunch'),
(DIN, 'Dinner'),
]
meal_time = models.IntegerField(
choices = MEAL_TIME_CHOICES,
default = MEAL_TIME_CHOICES[0]
)
class FoodItem(models.Model):
meal = models.ForeignKey(Meal, on_delete=models.CASCADE)
name = models.CharField(max_length=80)
Я хочу создать ModelForm, которая имеет несколько текстовых входов для FoodItems, чтобы несколько блюд могли быть сохранены и связаны с одним и тем же блюдом при одном отправлении формы.
Моя попытка сейчас позволяет мне отправлять только один продукт за раз.
class FoodItemForm(forms.ModelForm):
class Meta:
model = FoodItem
fields = ('name',)
Любая помощь в выполнении этого правильным способом будет очень признательна!
Создайте приложение с именем menu
:
|menu
├───migrations
| ...
├───templates
│ detail.html
│ list.html
│ __init__.py
│ admin.py
│ apps.py
│ forms.py
│ models.py
│ tests.py
│ urls.py
│ views.py
|project <--- the name of your "project"
│ asgi.py
│ settings.py
│ urls.py
│ wsgi.py
│ __init__.py
│templates <--- not used
│db.sqlite3
│manage.py
Добавьте приложение menu
к установленным приложениям:
project/settings.py
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'menu.apps.MenuConfig',
]
project/urls.py (на уровне проекта)
from django.contrib import admin
from django.urls import path, include
urlpatterns = [
path('admin/', admin.site.urls),
path('', include('menu.urls')),
]
menu/urls.py
from django.urls import path
from .views import list_view, detail_view
app_name = 'menu'
urlpatterns = [
path('', list_view, name='list'),
path('<pk>/', detail_view, name='detail'),
]
menu/models.py
import datetime
from django.db import models
class Meal(models.Model):
BFAST = 0
LUNCH = 1
DIN = 2
MEAL_TIME_CHOICES = [
(BFAST, 'Breakfast'),
(LUNCH, 'Lunch'),
(DIN, 'Dinner'),
]
meal_name = models.CharField(max_length=100)
date = models.DateField(default=datetime.date.today)
meal_time = models.IntegerField(choices=MEAL_TIME_CHOICES,default=0)
def __str__(self):
return self.meal_name
class FoodItem(models.Model):
meal = models.ForeignKey(Meal, on_delete=models.CASCADE)
food_item = models.CharField(max_length=80)
def __str__(self):
return self.food_item
Убедитесь, что вы makemigrations
и migrate
.
menu/forms.py
from django import forms
from django.forms.models import modelformset_factory
from .models import Meal, FoodItem
MealFormset = modelformset_factory(FoodItem, fields=('food_item',),
extra=5, can_delete=True)
menu/admin.py
from django.contrib import admin
from .models import Meal, FoodItem
class MealAdmin(admin.ModelAdmin):
pass
class FoodAdmin(admin.ModelAdmin):
pass
admin.site.register(Meal, MealAdmin)
admin.site.register(FoodItem, MealAdmin)
menu/views.py
from django.shortcuts import render, redirect
from .forms import MealFormset
from .models import Meal
def list_view(request):
context = {
'objects': Meal.objects.all(),
}
return render(request, 'list.html', context=context)
def detail_view(request, pk):
instance = Meal.objects.get(pk=pk)
formset = MealFormset(request.POST or None)
context = {
'object': instance,
'formset': formset,
}
if request.method == 'POST':
if formset.is_valid():
food_items = formset.save(commit=False)
if formset.deleted_forms:
for obj in formset.deleted_forms:
obj.instance.delete()
for food_item in food_items:
food_item.meal = instance
food_item.save()
return redirect('menu:list')
return render(request, 'detail.html', context=context)
menu/templates/list.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>List</title>
</head>
<body>
<div style="margin: auto; width: 50%; border: 1px solid black; padding: 20px;">
<a href="{% url 'admin:index' %}">Admin Panel</a>
<h1>Meals</h1>
{% for meal in objects %}
<div>
<a href="{% url 'menu:detail' meal.pk %}">{{ meal }}</a>
</div>
{% endfor %}
</div>
</body>
</html>
menu/templates/detail.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Food Items</title>
</head>
<body>
<div style="margin: auto; width: 50%; border: 1px solid black; padding: 20px;">
<form method="POST">
{% csrf_token %}
{{ formset.management_form }}
{% for field in formset %}
<div style="padding: 5px 40px;">{{ field }}</div>
{% endfor %}
<input type="submit" value="Submit">
</form>
</div>
</body>
</html>
Может быть, это не точно то, что вы хотите, но иллюстрирует некоторые ключевые понятия (я думаю).