【问题标题】:Populate a ManyToManyField填充多对多字段
【发布时间】:2016-01-21 01:06:25
【问题描述】:

我的models.py

class Ingredient(models.Model):
    name = models.CharField(max_length=16, unique=True)
    price = models.SmallIntegerField()
    def __str__(self):
        return self.name

class Topping(models.Model):
    name = models.CharField(max_length=32)
    ingredient = models.ForeignKey(Ingredient, related_name='indole', 
        blank=True, null=True, default='base')
    def __str__(self):
        return self.nome

class Pizza(models.Model):
    nome = models.CharField(max_length=32, unique=True)
    toppings = models.ManyToManyField(Topping)
    def __str__(self):
        return self.nome

在管理员中它工作!我可以添加浇头、披萨等。但我想使用脚本来填充。

我的script

import os
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'recipt.settings')

import django
django.setup()

from core.models import *

def populate():
    cheap = add_ingredient('Cheap', 3)
    base = add_ingredient('Base', 5)
    good = add_ingredient('Good', 10)

    cheese = add_topping('Cheese', None)
    tomato = add_topping('Tomato', None)
    olive = add_topping('Olive', None)  

    simple = add_pizza('Simple', cheese) #just one toppings for now
    complex = add_pizza('Complex', tomato)

def add_ingredient(name, price):
    i = Ingredient.objects.get_or_create(name=name, price=price)[0]
    i.save()
    return i

def add_topping(name, ingredient):
    t = Topping.objects.get_or_create(name=name, ingredient=ingredient)[0]
    t.save()
    return t

def add_pizza(name, toppings):
    p = Pizza.objects.get_or_create(name=name, toppings=toppings)[0]
    p.save()
    return p

if __name__ == '__main__':
    print ("Starting Core population script...")
    populate()

此脚本适用于配料和浇头,但不适用于披萨。

我的error(抱歉格式化):

正在启动核心填充脚本...

Traceback(最近一次调用最后一次):

文件“c:\Python34\Scripts\recipt\myvenv\lib\site-packages\django\db\mode ls\query.py”,第 465 行,在 get_or_create 中

返回 self.get(**lookup), False
文件“c:\Python34\Scripts\recipt\myvenv\lib\site-packages\django\db\mode ls\query.py",第 387 行,在获取中

self.model._meta.object_name

core.models.DoesNotExist:匹萨匹配查询不存在。

在处理上述异常的过程中,又发生了一个异常:

回溯(最近一次通话最后一次):
模块中的文件“populate_core.py”,第 437 行

填充()
文件“populate_core.py”,第 63 行,在填充中

simple = add_pizza('Simple', cheese)
文件“populate_core.py”,第 307 行,在 add_pizza 中

p = Pizza.objects.get_or_create(name=name, toppings=toppings)[0]
文件“c:\Python34\Scripts\recipt\myvenv\lib\site-packages\django\db\mode ls\manager.py”,第 122 行,在 manager_method 中

return getattr(self.get_queryset(), name)(*args, **kwargs)
文件“c:\Python34\Scripts\recipt\myvenv\lib\site-packages\django\db\mode ls\query.py”,第 467 行,在 get_or_create

返回 self._create_object_from_params(查找,参数)
_create_object_from_params 中的文件“c:\Python34\Scripts\recipt\myvenv\lib\site-packages\django\db\mode ls\query.py”,第 499 行

obj = self.create(**params)
文件“c:\Python34\Scripts\recipt\myvenv\lib\site-packages\django\db\mode ls\query.py”,第 399 行,在创建中

obj = self.model(**kwargs)
init

中的文件“c:\Python34\Scripts\recipt\myvenv\lib\site-packages\django\db\mode ls\base.py”,第 443 行

raise TypeError("'%s' is an invalid keyword argument for this function" % li st(kwargs)[0]) TypeError: 'toppings' is an invalid 此函数的关键字参数

有什么帮助吗?我在某处读到我应该将浇头留空并稍后添加,但是...

【问题讨论】:

    标签: python django m2m


    【解决方案1】:

    当您创建具有ManyToMany 字段的数据库记录时,您无法正常执行此操作。您必须创建对象,然后将内容添加到 ManyToMany 字段。像这样的东西。

    class Author(models.Model):
        name = models.CharField(max_length=100)
    class Article(models.Model):
        name = models.CharField(max_length=100)
        authors = models.ManyToManyField(Author)
    zach = Author("Zach Braff")
    zach.save()
    # Say Zach writes an article...
    # You can't do this because the authors field could have many things in it. 
    a1 = Article(name="Scrubs remake coming?", authors=zach)
    
    # Instead, you have to do this...
    a1 = Article(name="Scrubs remake coming?")
    a1.authors.add(zach)
    
    a1.save()
    

    您可能想要做的是将get_or_create() 替换为有效的等效项,如下所示。

    p = Pizza.objects.filter(name=name, toppings=toppings)
    # This is faster than `if p`
    if p.exists():
       return p
    else:
        p = Pizza.objects.create(name=name)
        p.toppings.add(toppings)
        p.save()
        return p
    

    我认为这应该可行。

    【讨论】:

      【解决方案2】:

      成功了,谢谢。

      这是我在script 中的新代码:

      simple = add_pizza('Simple', [cheese, tomato])
      complex = add_pizza('Complex', [cheese, tomato, olive])
      
      def add_pizza(name, toppings):
          p = Pizza.objects.filter(name=name)
          if p.exists():
              pass
          else:
          p = Pizza.objects.create(name=name)
          for t in toppings:
              p.toppings.add(t)
          p.save()
          return p
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2023-03-11
        • 2018-07-10
        • 1970-01-01
        • 2021-11-03
        • 2010-11-16
        • 1970-01-01
        • 1970-01-01
        • 2011-02-28
        相关资源
        最近更新 更多