Заполнить поле ManyToManyField

my 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

В админке работает! Я могу добавить начинку, пиццу и т. д. Но я хочу использовать скрипт для заполнения.

My 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

return self.get(**lookup), False
Файл "c:\Python34\Scripts\recipt\myvenv\lib\site-packages\django\db\mode ls\query.py", строка 387, в get

self.model._meta.object_name

core.models.DoesNotExist: Запрос соответствия пиццы не существует.

Во время обработки вышеупомянутого исключения произошло другое исключение:

Отслеживание (последний последний вызов):
Файл "populate_core.py", строка 437, в модуле

populate()
Файл "populate_core.py", строка 63, в файле populate.

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

return self._create_object_from_params(lookup, params)
Файл "c:\Python34\Scripts\recipt\myvenv\lib\site-packages\django\db\mode ls\query.py", строка 499, в _create_object_from_params

obj = self.create(**params)
Файл "c:\Python34\Scripts\recipt\myvenv\lib\site-packages\django\db\mode ls\query.py", строка 399, при создании

obj = self.model(**kwargs)
Файл "c:\Python34\Scripts\recipt\myvenv\lib\site-packages\django\db\mode ls\base.py", строка 443, в инициализировать

поднять TypeError("'%s' является недопустимым аргументом ключевого слова для этой функции" % li st(kwargs)[0]) TypeError: 'toppings' является недопустимым аргументом ключевого слова для этой функции

Любая помощь, пожалуйста? Я где-то читал, что я должен оставить поля пустыми и добавить позже, но...


person fabio    schedule 21.01.2016    source источник


Ответы (2)


Когда вы создаете запись базы данных с полем 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

Я думаю, это должно сработать.

person ddsnowboard    schedule 21.01.2016

Это работает, спасибо.

Вот мой новый код в 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
person fabio    schedule 21.01.2016