简体   繁体   中英

'opts = self.remote_field.model._meta' 'AttributeError: 'str' object has no attribute '_meta''

I am somewhat new to django, and I'm trying to build an airbnb clone to better understand django. I keep receiving an error when I attempt to start my server. I'm confused on how to resolve the error. It traces back to my virtual environment file, but I have never wrote any code directly into it. I have found that if I delete the contents of my admin.py file and my models.py file, it silences the error, and my server starts. I assume this suggests the error could be coming from one of those files. Here is the error code:

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'

Here's the Highlighted line in my related.py file:

opts = self.remote_field.model._meta

Here's the entire function:

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,
        )]

Here's my admin.py file:

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"


Here's my models.py file:

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

I'm not really sure where to start, and I'm way too scared to write anything directly into the virtual env. Does anyone have any ideas on where to start looking, or what the problem may be?

Just before the error in the stack, you can see this part;

  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)

This is coming in as part of the checks django does and tells us it's looking through the list_filter items in your admin classes.

I'd debug this, by editing this django code to add a print temporarily. Something like this before it does get_fields_from_path(obj.model, field) ;

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

That'll show you the last model and field to be ran before it causes an error.


Previous answer

So self.remote_field.model is a string value representing a model.

You can get to your model by doing this with string representations of models;

from django.apps import apps

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

So if you have a string value for self.remote_field.model then you should be able to do;

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

opts = MyModel._meta

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM