Django makemigrations AttributeError: объект «str» не имеет атрибута «_meta»

Я играл с фреймворком django и столкнулся с проблемой при выполнении команды makemigration. Вот копия модели и трассировка стека, которую она создает. Я видел пару сообщений с той же ошибкой, но ни одно из них не привело меня к решению моей проблемы здесь. Я работаю с джанго 1.9.4.

from django.db import models
import os, uuid

# Create your models here.
def video_directory_path(instance, folder):
    return os.path.join('video', str(instance.person.id), str(instance.video_id))

def photo_directory_path(instance, folder):
        return os.path.join('image', str(instance.person.id), str(instance.photo_id))


class Image(models.Model):
    name = models.CharField(max_length=128)
    photo_id = models.UUIDField(verbose_name='photo id', default=uuid.uuid4, editable=False, unique=True)
    photo = models.ImageField(upload_to=photo_directory_path)
    person = models.ForeignKey('Person', on_delete=models.CASCADE)
    movie = models.ForeignKey('Movie', on_delete=models.CASCADE)

    class Meta:
        db_table = 'Image'

    def __str__(self):
        return '[{0}- {1}]'.format(self.__class__.__name__, self.id)

    def __repr__(self):
        return self.__str__()


class Video(models.Model):
    name = models.CharField(max_length=128)
    video_id = models.UUIDField(verbose_name='video id', default=uuid.uuid4, editable=False, unique=True)
    video = models.FileField(upload_to=video_directory_path)
    person = models.ForeignKey('Person', on_delete=models.CASCADE)
    movie = models.ForeignKey('Movie', on_delete=models.CASCADE)

    class Meta:
        db_table = 'Video'

    def __str__(self):
        return '[{0}-{1}]'.format(self.__class__.__name__, self.id)

    def __repr__(self):
        return self.__str__()


class Filmography(models.Model):
    filmography = models.CharField(max_length=128, db_index=True)

    class Meta:
        db_table = 'Filmography'

    def __str__(self):
        return '[{0}-{1}]'.format(self.__class__.__name__, self.id)

    def __repr__(self):
        return self.__str__()


class Person(models.Model):
    bio = models.TextField()
    filmography = models.ManyToManyField('Filmography')
    photos = models.ManyToManyField(
        'Image',
        through='ImagePerson',
        through_fields=('person', 'photo')
    )

    class Meta:
        abstract = True

    def __str__(self):
        return '[{0}-{1}]'.format(self.__class__.__name__, self.id)

    def __repr__(self):
        return self.__str__()


class Profile(Person):
    first_name = models.CharField(max_length=128, verbose_name="first name")
    last_name = models.CharField(max_length=128, verbose_name="last name")
    dob = models.DateField()

    class Meta:
        index_together = ["first_name", "last_name"]
        db_table = 'Profile'


class Character(Person):
    name = models.CharField(max_length=128)

    class Meta:
        db_table = 'Character'


class Crew(models.Model):
    name = models.CharField(max_length=256)
    members = models.ManyToManyField(
        'Profile',
        through='MovieCrew',
        through_fields=('crew', 'profile'),
    )

    class Meta:
        db_table = 'Crew'

        def __str__(self):
            return '{0}: {1}'.format(self.__class__.__name__, self.name)

    def __repr__(self):
        return self.__str__()


class MovieCrew(models.Model):
    crew = models.ForeignKey(
        'Crew',
        on_delete=models.CASCADE,
    )
    profile = models.ForeignKey(
        'Profile',
        on_delete=models.CASCADE,
    )
    role = models.CharField(max_length=256)

    class Meta:
        db_table = 'MovieCrew'


class Genre(models.Model):
    genre = models.CharField(max_length=128, db_index=True)

    class Meta:
        db_table = 'Genre'


class Movie(models.Model):
    name = models.CharField(max_length=128, db_index=True)
    summary = models.CharField(max_length=256)
    story = models.CharField(max_length=256)
    release_date = models.DateField()

    crew = models.OneToOneField(
        'Crew',
        on_delete=models.CASCADE,
    )
    genre = models.ManyToManyField('Genre')
    photos = models.ManyToManyField('Image')
    videos = models.ManyToManyField('Video')

    class Meta:
        db_table = 'Movie'
        get_latest_by = 'release_date'

    def __str__(self):
        return '[{0}-{1}]'.format(self.__class__.__name__, self.name)

    def __repr__(self):
        return self.__str__()

и трассировка стека ошибок

Traceback (most recent call last):
  File "manage.py", line 10, in <module>
    execute_from_command_line(sys.argv)
  File "C:\Python34\lib\site-packages\django\core\management\__init__.py", line 353, in execute_from_command_line
    utility.execute()
  File "C:\Python34\lib\site-packages\django\core\management\__init__.py", line 345, in execute
    self.fetch_command(subcommand).run_from_argv(self.argv)
  File "C:\Python34\lib\site-packages\django\core\management\base.py", line 348, in run_from_argv
    self.execute(*args, **cmd_options)
  File "C:\Python34\lib\site-packages\django\core\management\base.py", line 398, in execute
    self.check()
  File "C:\Python34\lib\site-packages\django\core\management\base.py", line 426, in check
    include_deployment_checks=include_deployment_checks,
  File "C:\Python34\lib\site-packages\django\core\checks\registry.py", line 75, in run_checks
    new_errors = check(app_configs=app_configs)
  File "C:\Python34\lib\site-packages\django\core\checks\model_checks.py", line 28, in check_all_models
    errors.extend(model.check(**kwargs))
  File "C:\Python34\lib\site-packages\django\db\models\base.py", line 1170, in check
    errors.extend(cls._check_fields(**kwargs))
  File "C:\Python34\lib\site-packages\django\db\models\base.py", line 1249, in _check_fields
    errors.extend(field.check(from_model=cls, **kwargs))
  File "C:\Python34\lib\site-packages\django\db\models\fields\related.py", line 1165, in check
    errors.extend(self._check_relationship_model(**kwargs))
  File "C:\Python34\lib\site-packages\django\db\models\fields\related.py", line 1366, in _check_relationship_model
    for f in through._meta.fields:
AttributeError: 'str' object has no attribute '_meta'

person legend    schedule 04.04.2016    source источник


Ответы (3)


Кажется, в этом файле нет класса с именем ImagePerson, который вы устанавливаете для through (сквозной таблицы) в M2M на Person.

person dreamriver    schedule 04.04.2016
comment
Ух ты! Спасибо... попробую, посмотрим. Это проблема джанго? (Это неясное сообщение об исключении) - person legend; 04.04.2016
comment
Поэтому обычно вы опускаете объявление through, как и в других определениях ManyToMany. Обычно вы передаете пользовательский только в том случае, если есть какие-то дополнительные данные, которые вы хотите сохранить в этой модели. Django позволяет передавать модель или строку в большинстве мест... Я путаюсь, не уверен, в чем ваш вопрос. - person dreamriver; 04.04.2016
comment
Как сказал dreamriver, обычно вам не нужно объявлять таблицу through, если вам не нужна дополнительная информация (например, добавленная дата или что-то в этом роде). Django сам создаст сквозную таблицу и будет управлять ею за вас. Однако вы также можете объявить поле through, если вы работаете с устаревшей базой данных, в которой уже есть существующие сквозные таблицы, которые django должен использовать вместо создания своих собственных. Вы получите эту ошибку, если пренебрежете импортом модели в файл, ссылающийся на нее, или забудете определить ее. - person Nick BL; 17.04.2019

Проблема с отступами в классе Crew? Ваш метод str здесь, похоже, определен в Meta:

class Crew(models.Model):
    name = models.CharField(max_length=256)
    members = models.ManyToManyField(
        'Profile',
        through='MovieCrew',
        through_fields=('crew', 'profile'),
    )

    class Meta:
        db_table = 'Crew'


        def __str__(self):
            return '{0}: {1}'.format(self.__class__.__name__, self.name)

    def __repr__(self):
        return self.__str__()

Это действительно то, что вам нужно?

person kjarsenal    schedule 04.04.2016

Для некоторых людей, получающих эту ошибку, не забудьте добавить недавно созданное приложение в Django INSTALLED_APPS, чтобы ваша промежуточная модель ManyToMany through= была распознана.

person sivabudh    schedule 18.08.2019