‘opts = self.remote_field.model._meta’ ‘Ошибка атрибута: объект ‘str’ не имеет атрибута ‘_meta»

#python-3.x #django #django-models #django-rest-framework #virtualenv

Вопрос:

Я несколько новичок в django и пытаюсь создать клон airbnb, чтобы лучше понять django. Я продолжаю получать сообщение об ошибке при попытке запустить свой сервер. Я не понимаю, как устранить ошибку. Он ведет к моему файлу виртуальной среды, но я никогда не писал в него никакого кода напрямую. Я обнаружил, что если я удалю содержимое своего admin.py досье и мое models.py файл, он отключает ошибку, и мой сервер запускается. Я предполагаю, что это говорит об ошибке, которая может исходить от одного из этих файлов. Вот код ошибки:

 Exception in thread django-main-thread:
Traceback (most recent call last):
  File "/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/threading.py", line 954, in _bootstrap_inner
    self.run()
  File "/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/threading.py", line 892, in run
    self._target(*self._args, **self._kwargs)
  File "/Users/AUTH_SYSTEM/backend/venv/lib/python3.9/site-packages/django/utils/autoreload.py", line 64, in wrapper
    fn(*args, **kwargs)
  File "/Users/AUTH_SYSTEM/backend/venv/lib/python3.9/site-packages/django/core/management/commands/runserver.py", line 118, in inner_run
    self.check(display_num_errors=True)
  File "/Users/AUTH_SYSTEM/backend/venv/lib/python3.9/site-packages/django/core/management/base.py", line 419, in check
    all_issues = checks.run_checks(
  File "/Users/AUTH_SYSTEM/backend/venv/lib/python3.9/site-packages/django/core/checks/registry.py", line 76, in run_checks
    new_errors = check(app_configs=app_configs, databases=databases)
  File "/Users/AUTH_SYSTEM/backend/venv/lib/python3.9/site-packages/django/contrib/admin/checks.py", line 54, in check_admin_app
    errors.extend(site.check(app_configs))
  File "/Users/AUTH_SYSTEM/backend/venv/lib/python3.9/site-packages/django/contrib/admin/sites.py", line 92, in check
    errors.extend(modeladmin.check())
  File "/Users/AUTH_SYSTEM/backend/venv/lib/python3.9/site-packages/django/contrib/admin/options.py", line 122, in check
    return self.checks_class().check(self, **kwargs)
  File "/Users/AUTH_SYSTEM/backend/venv/lib/python3.9/site-packages/django/contrib/admin/checks.py", line 648, in check
    *self._check_list_filter(admin_obj),
  File "/Users/AUTH_SYSTEM/backend/venv/lib/python3.9/site-packages/django/contrib/admin/checks.py", line 804, in _check_list_filter
    return list(chain.from_iterable(
  File "/Users/AUTH_SYSTEM/backend/venv/lib/python3.9/site-packages/django/contrib/admin/checks.py", line 805, in <genexpr>
    self._check_list_filter_item(obj, item, "list_filter[%d]" % index)
  File "/Users/AUTH_SYSTEM/backend/venv/lib/python3.9/site-packages/django/contrib/admin/checks.py", line 848, in _check_list_filter_item
    get_fields_from_path(obj.model, field)
  File "/Users/AUTH_SYSTEM/backend/venv/lib/python3.9/site-packages/django/contrib/admin/utils.py", line 487, in get_fields_from_path
    parent = get_model_from_relation(fields[-1])
  File "/Users/AUTH_SYSTEM/backend/venv/lib/python3.9/site-packages/django/contrib/admin/utils.py", line 438, in get_model_from_relation
    return field.get_path_info()[-1].to_opts.model
  File "/Users/AUTH_SYSTEM/backend/venv/lib/python3.9/site-packages/django/db/models/fields/related.py", line 712, in get_path_info
    opts = self.remote_field.model._meta
AttributeError: 'str' object has no attribute '_meta'
 

Вот выделенная строка в моем related.py файл:

 opts = self.remote_field.model._meta
 

Вот вся функция:

 def get_path_info(self, filtered_relation=None):
        """Get path from this field to the related model."""
        opts = self.remote_field.model._meta
        from_opts = self.model._meta
        return [PathInfo(
            from_opts=from_opts,
            to_opts=opts,
            target_fields=self.foreign_related_fields,
            join_field=self,
            m2m=False,
            direct=True,
            filtered_relation=filtered_relation,
        )]
 

Вот мой admin.py файл:

 from django.contrib import admin

# Register your models here.
#New
from django.contrib import admin
from django.utils.html import mark_safe
from .models import Room, RoomType, Amenity, Facility, HouseRule, Photo


@admin.register(RoomType, Amenity, Facility, HouseRule)
class ItemAdmin(admin.ModelAdmin):
    """Register model classes inherited from the AbstractItem model"""

    list_display = ("name", "used_by")

    def used_by(self, obj):
        return obj.rooms.count()


@admin.register(Photo)
class PhotoAdmin(admin.ModelAdmin):
    """Register Photo model at admin panel"""

    list_display = ("__str__", "get_thumbnail")

    def get_thumbnail(self, obj):
        return mark_safe(f'<img width="50px" src="{obj.file.url}" />')

    get_thumbnail.short_description = "Thumbnail"


class PhotoInlineAdmin(admin.TabularInline):
    """Photo model's inline admin"""

    model = Photo


@admin.register(Room)
class RoomAdmin(admin.ModelAdmin):
    """Register Room model at admin panel

    Filter by:
        instant_book      : BooleanField
        host.is_superhost : BooleanField
        city              : CharField
        room_type         : RoomType Model
        amenities         : Amenity Model
        facilities        : Facility Model
        house_rules       : HouseRule Model
        country           : CharField

    Search by:
        city              : exact
        host.username     : startwith

    Admin function :
        count_amenities   : return amenities count
        count_facilities  : return facilities count
        count_house_rules : return house_rules count
    """

    inlines = (PhotoInlineAdmin,)

    fieldsets = (
        (
            "Basic Info",
            {"fields": ("name", "description", "country", "address", "price")},
        ),
        ("Times", {"fields": ("check_in", "check_out", "instant_book")}),
        ("Spaces", {"fields": ("guests", "beds", "bedrooms", "baths")}),
        (
            "More About the Space",
            {
                "classes": ("collapse",),
                "fields": ("amenities", "facilities", "house_rules"),
            },
        ),
        ("Last Details", {"fields": ("host",)}),
    )

    raw_id_fields = ("host",)

    list_display = (
        "name",
        "country",
        "city",
        "price",
        "address",
        "guests",
        "beds",
        "bedrooms",
        "baths",
        "check_in",
        "check_out",
        "instant_book",
        "count_amenities",
        "count_photos",
        "total_rating",
    )
    list_filter = (
        "instant_book",
        "host__is_superhost",
        "city",
        "room_type",
        "amenities",
        "facilities",
        "house_rules",
        "country",
    )
    filter_horizontal = ("amenities", "facilities", "house_rules")
    search_fields = ("=city", "^host__username")

    def count_amenities(self, obj):
        return obj.amenities.count()

    def count_photos(self, obj):
        return obj.photos.count()

    count_photos.short_description = "Photo Count"


 

Вот мой models.py файл:

 from django.db import models

# Create your models here.
#New
from django.urls import reverse
from django_countries.fields import CountryField
from core.models import AbstractTimeStamp


class AbstractItem(AbstractTimeStamp):
    """Abstract Item Model

    Inherit:
        AbstractTimeStamp

    Fields:
        name       : CharField
        created_at : DateTimeField
        updated_at : DateTimeField

    Method:
        __str__ : return name
    """

    name = models.CharField(max_length=80, unique=True)

    class Meta:
        abstract = True

    def __str__(self):
        return self.name


class RoomType(AbstractItem):
    """RoomType Model

    Inherit:
        AbstractItem
    """

    class Meta:
        verbose_name = "Room Type"


class Amenity(AbstractItem):
    """Amenity Model

    Inherit:
        AbstractItem
    """

    class Meta:
        verbose_name_plural = "Amenities"


class Facility(AbstractItem):
    """Facility Model

    Inherit:
        AbstractItem
    """

    class Meta:
        verbose_name_plural = "Facilities"


class HouseRule(AbstractItem):
    """HouseRule Model

    Inherit:
        AbstractItem
    """

    class Meta:
        verbose_name = "House Rule"


class Photo(AbstractTimeStamp):
    """Photo Model

    Inherit:
        AbstractTimeStamp

    Fields:
        caption    : CharField
        file       : ImageField
        room       : Room Model (1:N)
        created_at : DateTimeField
        updated_at : DateTimeField

    Method:
        __str__ : return caption
    """

    caption = models.CharField(max_length=80)
    file = models.ImageField(upload_to="room_photos")
    room = models.ForeignKey("Room", related_name="photos", on_delete=models.CASCADE)

    def __str__(self):
        return self.caption


class Room(AbstractTimeStamp):
    """Room Model

    Inherit:
        AbstractTimeStamp

    Fields:
        name         : CharField
        description  : TextField
        country      : CountryField
        city         : CharField
        price        : IntegerField
        address      : CharField
        guests       : IntegerField
        beds         : IntegerField
        bedrooms     : IntegerField
        baths        : IntegerField
        check_in     : TimeField
        check_out    : TimeField
        instant_book : BooleanField
        host         : users app User model (1:N)
        room_type    : RoomType model (1:N)
        amenities    : Amenity model (N:N)
        facilities   : Facility model (N:N)
        house_rules  : HouseRule model(N:N)
        created_at   : DateTimeField
        updated_at   : DateTimeField

    Method:
        __str__      : return name
        save         : change capitalized city name and save
        total_rating : return all reviews rating avg
        first_photo  : return room's first photo file url
    """

    name = models.CharField(max_length=140)
    description = models.TextField()
    country = CountryField()
    city = models.CharField(max_length=80)
    price = models.IntegerField()
    address = models.CharField(max_length=140)
    guests = models.IntegerField()
    beds = models.IntegerField()
    bedrooms = models.IntegerField()
    baths = models.IntegerField()
    check_in = models.TimeField()
    check_out = models.TimeField()
    instant_book = models.BooleanField(default=False)
    host = models.ForeignKey(
        "users.User", related_name="rooms", on_delete=models.CASCADE
    )
    room_type = models.ForeignKey(
        "RoomType", related_name="rooms", on_delete=models.SET_NULL, null=True
    )
    amenities = models.ManyToManyField("Amenity", related_name="rooms", blank=True)
    facilities = models.ManyToManyField("Facility", related_name="rooms", blank=True)
    house_rules = models.ManyToManyField("HouseRule", related_name="rooms", blank=True)

    def __str__(self):
        return self.name

    def save(self, *args, **kwargs):
        self.city = str.capitalize(self.city)
        super().save(*args, **kwargs)

    def get_absolute_url(self):
        return reverse("rooms:detail", kwargs={"pk": self.pk})

    def total_rating(self):
        all_reviews = self.reviews.all()

        if len(all_reviews) == 0:
            return 0

        all_ratings = 0

        for review in all_reviews:
            all_ratings  = review.rating_average()

        return round(all_ratings / len(all_reviews), 2)

    def first_photo(self):
        try:
            (photo,) = self.photos.all()[:1]
            return photo.file.url
        except Exception:
            return None

    def get_next_four_photos(self):
        photos = self.photos.all()[1:5]
        return photos

 

Я не совсем уверен, с чего начать, и я слишком напуган, чтобы писать что-либо непосредственно в виртуальную среду. У кого-нибудь есть какие-либо идеи о том, с чего начать поиски или в чем может быть проблема?

Ответ №1:

Непосредственно перед ошибкой в стеке вы можете увидеть эту часть;

   File "/Users/AUTH_SYSTEM/backend/venv/lib/python3.9/site-packages/django/contrib/admin/checks.py", line 848, in _check_list_filter_item
    get_fields_from_path(obj.model, field)
 

Это входит в состав проверок, которые проводит django, и говорит нам, что он просматривает list_filter элементы в ваших классах администратора.

Я бы отладил это, отредактировав этот код django, чтобы временно добавить печать. Что — то вроде этого, прежде чем это произойдет get_fields_from_path(obj.model, field) ;

print(f"{obj.model}, {field}")

Это покажет вам последнюю модель и поле, которые необходимо запустить, прежде чем это вызовет ошибку.


Предыдущий ответ

Так self.remote_field.model же как и строковое значение, представляющее модель.

Вы можете добраться до своей модели, выполнив это со строковыми представлениями моделей;

 from django.apps import apps

Site = apps.get_model('sites.Site')
 

Поэтому, если у вас есть строковое значение для self.remote_field.model , вы должны быть в состоянии сделать;

 MyModel = apps.get_model(self.remote_field.model)

opts = MyModel._meta
 

Комментарии:

1. Я все еще немного не понимаю, как реализовать ваше решение. В какой файл мне следует это добавить? Я предполагаю, что это должно войти в models.py файл, но я не уверен. Мой вопрос больше сосредоточен на том, какую защиту, класс или функцию я должен изменить.

2. @ethan4024 о, понятно. Я ответил на это слишком поздно ночью — ошибка, которую вы разместили, пришла прямо из django. Я еще раз взгляну на вещи и посмотрю, смогу ли я увидеть ошибку с вашим фактическим кодом.

3. Не беспокойтесь, вы направили меня в очень полезном направлении. Я думаю, что ошибка где-то в admin.py или в models.py файл, потому что, когда я удаляю их содержимое, ошибка устраняется. Чтобы уточнить, поскольку я не заявлял об этом ранее, я запускаю django 3.2.4.

4. @ethan4024 Трассировка стека показывает, что это ошибка из list_filter проверок. Вам нужно будет немного разобраться, но я добавил несколько советов.