Django模型与ManyToMany不保存

时间:2017-06-01 18:58:11

标签: django django-models django-templates django-views

我有一个菜单列表 - 菜单上列出了项目。

models.py

class Menu(models.Model):
    season = models.CharField(max_length=20)
    items = models.ManyToManyField('Item', related_name='items')
    created_date = models.DateTimeField(default=timezone.now)
    expiration_date = models.DateTimeField(blank=True, null=True)

    def __str__(self):
        return self.season

class Item(models.Model):

    name = models.CharField(max_length=200)
    description = models.TextField()
    chef = models.ForeignKey('auth.User')
    created_date = models.DateTimeField(
            default=timezone.now)
    standard = models.BooleanField(default=False)
    ingredients = models.ManyToManyField(
        'Ingredient', related_name='ingredients'
    )

    def __str__(self):
        return self.name

class Ingredient(models.Model):
    name = models.CharField(max_length=200)

    def __str__(self):
        return self.name

出于某种原因 - 在管理员 - 我可以编辑菜单,它将正确保存项目 - 但如果我在菜单的编辑视图中这样做,它不会保存项目(但它确实保存本赛季和expiration_date)。这就是为什么我想也许是ManyToMany关系?有什么想法吗?

views.py

def edit_menu(request, pk):
    menu = get_object_or_404(Menu, pk=pk)
    items = Item.objects.all()
    admin = User.objects.get(username="admin")
    if request.method == "POST":
        ingredient = Ingredient(name="bug")
        ingredient.save()
        items = []

        for i in request.POST.getlist('items'):
            item = Item(name=i, chef=admin, description = "your description here", standard=False)
            item.save()
            items.append(item)
            item.ingredients.add(ingredient)

        if not Menu.objects.filter(pk=pk).exists():
            menu=Menu(season=request.POST.get('season', ''),
                      expiration_date=datetime.strptime(request.POST.get('expiration_date', ''), '%m/%d/%Y'))

        else:
            menu=Menu.objects.get(pk=pk)
            menu.items.delete()

        menu.save()

        for item in items:
            menu.items.add(item)
            return redirect('menu_detail', pk=menu.pk)

    return render(request, 'menu/change_menu.html', {
    'menu': menu,
    'items': items,
})

和菜单详细信息页面

模板

{% extends "layout.html" %}
{% block content %}
        <div class="content container">
            <div class="row">
                <div class="col-md-8">
                    <div class="post">
                        <h1>
                            {% if user.is_authenticated %}
                                <a class="btn btn-default" href="{% url 'menu_edit' pk=menu.pk %}"><span class="glyphicon glyphicon-pencil"></span></a>
                            {% endif %}
                            {{ menu.season }}
                        </h1>
                        <h2>On the menu this season:</h2>
                        <ul>
                            {% for item in menu.items.all %}
                                <li><a href="{% url 'item_detail' pk=item.pk %}">{{ item }}</a></li>
                            {% endfor %}
                        </ul>
                        {% if menu.expiration_date %}
                            <div class="date">
                                Menu expires on {{ menu.expiration_date|date:"F j, Y" }}
                            </div>
                        {% endif %}
                    </div>
                </div>
            </div>
        </div>
{% endblock %}

更新 - 将编辑视图更改为此...现在出现多对多错误

def edit_menu(request, pk):
    menu = get_object_or_404(Menu, pk=pk)
    items = Item.objects.all()
    admin = User.objects.get(username="admin")
    if request.method == "POST":
        ingredient = Ingredient(name="bug")
        ingredient.save()
        item = Item(name=request.POST.get('items', ''), chef=admin, description = "your description here", standard=False)
        item.save()
        item.ingredients.add(ingredient)
        menu = Menu(season=request.POST.get('season', ''),
                    expiration_date=datetime.strptime(request.POST.get('expiration_date', ''), '%m/%d/%Y'))
        menu.save()
        menu.items.add(item)
        return redirect('menu_detail', pk=menu.pk)

    return render(request, 'menu/change_menu.html', {
    'menu': menu,
    'items': items,
})

更新 - 在下面添加change_menu模板

{% extends "layout.html" %}
{% block content %}
        <div class="content container">
            <div class="row">
                <div class="col-md-8">
                    <h1>Change menu</h1>
                    <form action="" method="POST">{% csrf_token %}
                        <label for="season">Season:</label>
                        <input type="text" name="season" value="{{ menu.season }}">
                        <br />
                        <label for="items">Items:</label>
                        <select multiple>
                        {% for item in items %}
                            <option value="{{ item }}">{{ item}}</option>
                        {% endfor %}
                        </select>
                        <br />
                        <label for="expiration_date">Expiration Date:</label>
                         <input type="text" name="expiration_date" value="{{ menu.expiration_date|date:"m/d/Y" }}">
                        <br />
                        <input type="submit" value="Submit" /> 
                    </form>
                </div>
            </div>
        </div>
{% endblock %}

下添加new_menu模板
{% extends "layout.html" %}
{% block content %}

   <div class="content container">
            <div class="row">
                <div class="col-md-8">
                    <h1>Create New Menu</h1>
                    <form method="POST" action="">
                        {% csrf_token %}
                        {{ form.as_p }}
                        <input type="submit" class="button" value="Save">
                    </form>
                </div>
                </div>
       </div>


{% endblock %}

2 个答案:

答案 0 :(得分:1)

首先创建并保存ManyToMany个对象,然后添加AFTER they have already been saved

ingredient = Ingredient(add parameters here)
ingredient.save()
# put items in a list so you can add them to menu later
items = []
# make new items from option box in template
for i in request.POST.getlist('items'):
    item = Item(name=i, chef=admin, description = "your description here", standard=False)
    item.save()
    items.append(item)
item.ingredients.add(ingredient)

if not Menu.objects.filter(pk=pk).exists():
    menu=Menu(season=request.POST.get('season', ''), expiration_date=datetime.strptime(request.POST.get('expiration_date', ''), '%m/%d/%Y'))
else:
    menu=Menu.objects.get(pk=pk)
    # we will be replacing the old menu items
    menu.items.clear()
menu.save()
for item in items:
    menu.items.add(item)

答案 1 :(得分:1)

你需要像这样编辑你的观点,

def edit_menu(request, pk):
    menu = get_object_or_404(Menu, pk=pk)
    items = Item.objects.all()
    if request.method == "POST":
        item_name = request.POST.get('items')
        season = request.POST.get('season')
        exp_date = datetime.strptime(request.POST.get('expiration_date'), '%m/%d/%Y')
        try:
            item = Item.objects.get(name=item_name)
        except:
            item = Item.objects.create(name=item_name, description = "description_here", ingredients="ingredients_here", standard=False)
        menu = Menu.objects.create(season=season, expiration_date=exp_date)
        menu.items.add(item)
        menu.save()
        return redirect('menu_detail', pk=menu.pk)

    return render(request, 'menu/change_menu.html', {
    'menu': menu,
    'items': items,
})

如果不将模型提交到数据库,则无法添加多对多关系。首先,您必须保存菜单对象,然后需要将item添加到菜单的items