#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
проверок. Вам нужно будет немного разобраться, но я добавил несколько советов.