【问题标题】:Django Model With ManyToMany Not Saving多对多不保存的 Django 模型
【发布时间】:2017-11-03 01:11:39
【问题描述】:

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

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

出于某种原因——在管理员中——我可以编辑菜单,它会正确保存项目——但如果我在菜单的编辑视图中这样做,它不会保存项目(但它会保存季节和到期日期)。这就是为什么我认为这可能是多对多关系?有什么想法吗?

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 %}

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

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,
})

UPDATE --在下面添加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 %}

【问题讨论】:

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


    【解决方案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)
    

    【讨论】:

      【解决方案2】:

      你需要像这样编辑你的视图,

      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中。

      【讨论】:

      • 在尝试下面的 Matt 的解决方案时尝试过并得到同样的错误
      • "" 需要有字段“id”的值才能使用这种多对多关系。
      • 同样的错误“”需要有一个字段“id”的值才能使用这种多对多关系。指向这一行:
      • item = Item.objects.get(name=request.POST.get('items', ''))
      • 你能发布回溯吗?
      猜你喜欢
      • 2014-08-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-08-02
      • 2017-12-16
      • 2018-07-05
      相关资源
      最近更新 更多