ValueError: переменная должна иметь значение для поля "id", прежде чем можно будет использовать это отношение многие ко многим - Django - PullRequest
0 голосов
/ 28 сентября 2018

Я создал модель данных в Django, и теперь я создал сценарий для автоматического заполнения моделей с использованием значений, извлеченных из Интернета.Однако, когда я запускаю сценарий, я получаю следующую ошибку: ValueError: переменная должна иметь значение для поля "id", прежде чем можно будет использовать это отношение многие ко многим

Модели.py

class Books(models.Model):
    title = models.CharField(max_length=100)

    def __str__(self):
        return self.title

    class Meta:
        ordering = ['-title']

class Author(models.Model):
    book = models.ManyToManyField(Books)
    first_name = models.CharField(max_length=150)
    last_name = models.CharField(max_length=200)

    def __str__(self):
        return "{} {}".format(self.first_name, self.last_name)

    class Meta:
        ordering = ['last_name','first_name']


class Book_details(models.Model):
    book = models.ForeignKey(Books, 
                            on_delete=models.CASCADE, 
                            null=True) # models.SET_NULL weggehaald
    pages = models.CharField(max_length=250)
    publ_year = models.CharField(max_length=250)
    edition = models.CharField(max_length=30) # paperback, hardcover, audiobook, etc


    def __str__(self):
        return "{} - pages: <{}>, edition: <{}>".format(self.book.title, 
                                                    self.pages, 
                                                    self.edition)# 

class Cover(models.Model):
    book = models.OneToOneField(Books, 
                            on_delete=models.CASCADE)
    path = models.CharField(max_length=500)

    def __str__(self):
        return "<Cover <path={}>".format(self.id, self.path)

populate_script

def add_book(title):
    b = Books.objects.get_or_create(title = title)[0]
    print(b)
    b.save()
    return b

def populate(scraped_tuple):
    fake = Faker()

    for _ in range(len(scraped_tuple)):

        b_title = scraped_tuple[_][0][0]
        new_book = add_book(b_title)

        b_author_first = scraped_tuple[_][0][1].split(" ")[0]
        b_author_last = scraped_tuple[_][0][1].split(" ")[1]
        b_pages = scraped_tuple[_][0][2].split(" ")[0]
        b_publ_year = fake.year()
        b_edition = scraped_tuple[_][0][3].split(",")[0]
        b_cover = scraped_tuple[_][0][4]

        new_details = Book_details.objects.get_or_create(book = new_book, pages = b_pages, publ_year = b_publ_year, edition = b_edition)[0]

        new_author = Author.objects.get_or_create(book = new_book, first_name = b_author_first, last_name = b_author_last)[0]

        new_cover = Cover.objects.get_or_create(book = new_book, path = b_cover)[0]

scraped_tuple - это возвращаемое значение от веб-мастера, содержащее подробности.

(Часть) Traceback:

Books.models.DoesNotExist: Author matching query does not exist.
  File "C:\path\to\LibraryApp\Library_WebA
pp\Library\populate.py", line 45, in populate
    new_author = Author.objects.get_or_create(book = new_book, first_name = b_author_first, last_nam
e = b_author_last)[0]

Затем:

ValueError: "<Author: Mary McCarthy>" needs to have a value for field "id" before this many-to-many relationship can be used.

Итак, похоже, что что-то идет не так, как надо при попытке выполнить оператор new_author, из-заМногочисленное поле «Книга» в авторской модели.Как я могу решить это.Нужна ли мне аналогичная функция для объекта Author, как у Book в add_book ()?Кажется, оператор new_details выполняется просто отлично (title и book_details правильно отображаются в базе данных в административной части Django).

1 Ответ

0 голосов
/ 29 сентября 2018

Как уже упоминалось в документах , пользователь .add () связывает записи во многих со многими полями.

def populate(scraped_tuple):
fake = Faker()

for _ in range(len(scraped_tuple)):

    b_title = scraped_tuple[_][0][0]
    new_book = add_book(b_title)

    b_author_first = scraped_tuple[_][0][1].split(" ")[0]
    b_author_last = scraped_tuple[_][0][1].split(" ")[1]
    b_pages = scraped_tuple[_][0][2].split(" ")[0]
    b_publ_year = fake.year()
    b_edition = scraped_tuple[_][0][3].split(",")[0]
    b_cover = scraped_tuple[_][0][4]

    new_details = Book_details.objects.get_or_create(book = new_book, pages = b_pages, publ_year = b_publ_year, edition = b_edition)[0]

    new_author = Author.objects.get_or_create(first_name = b_author_first, last_name = b_author_last)[0]

    # add many to many fields this way:
    new_author.book.add(new_book)

    new_cover = Cover.objects.get_or_create(book = new_book, path = b_cover)[0]
...