Ошибка Django: объект 'DetailView' не имеет атрибута '_meta'
Это меня поразило. Я строю модель с Django & REST API, и у меня проблемы с отображением DetailView для отдельных автомобилей в браузере. ListView работает нормально, но я включу и этот код, поскольку они взаимосвязаны.
В частности, я не могу заставить функцию get_object() работать должным образом.
Первый подход, который я попробовал, использовал следующее:
views.py
class CarDetailView(generics.RetrieveUpdateDestroyAPIView):
renderer_classes = [TemplateHTMLRenderer]
template_name = 'car-detail.html'
queryset = Car.objects.all()
lookup_field = Car.id
@action(detail=True, renderer_classes=[TemplateHTMLRenderer])
def get(self, request, *args, **kwargs):
car = self.get_object()
return Response({
'car': car,
})
Хотя страница отображалась правильно и без ошибок, ни один из тегов шаблона не работал. Только {{ car.model }}, который вернул None.
Поэтому я изменил код, чтобы использовать self.get_object()
class CarDetailView(generics.GenericAPIView):
renderer_classes = [TemplateHTMLRenderer]
template_name = 'car-detail.html'
queryset = Car.objects.all()
lookup_field = Car.id
def get(self, request, id):
serializer_class = CarSerializer
car = self.get_object()
id = Car.id
return Response({
'car': car,
})
но это вызывает ошибку:
"AttributeError at /rentals/car/43c9b98d-9f2d-473f-9c34-7b2e25630278 Объект 'CarDetailView' не имеет атрибута '_meta'"
Можете ли вы помочь с этим? Я просмотрел большинство предыдущих вопросов здесь (именно здесь я научился передавать self в функции get и т.д...), но я все еще застрял.
Вот код:
views.py
class CarListView(generics.ListCreateAPIView):
renderer_classes = [TemplateHTMLRenderer]
template_name = 'car-list.html'
def get(self, request):
car_list = Car.objects.all()
serializer_class = CarSerializer
return Response({
'car_list': car_list,
})
class CarDetailView(generics.GenericAPIView):
renderer_classes = [TemplateHTMLRenderer]
template_name = 'car-detail.html'
queryset = Car.objects.all()
lookup_field = Car.id
def get(self, request, id):
serializer_class = CarSerializer
car = self.get_object()
id = Car.id
return Response({
'car': car,
})
serializers.py class CarSerializer(serializers.ModelSerializer): url = serializers.HyperlinkedIdentityField(view_name='rental:car-detail', format='html')
class Meta:
model = Car
fields = ['url', 'id', 'manufacturer', 'model', 'owner', 'color', 'year']
models.py
class Car(models.Model):
manufacturer = models.ForeignKey(Manufacturer, on_delete=models.SET_NULL, null=True)
model = models.ForeignKey(CarModel, on_delete=models.SET_NULL, null=True)
# Model year. Validator ensures that no model year can be set in the future.
year = models.IntegerField(validators=[MaxValueValidator(int(datetime.date.today().year) + 1)], null=True, default=2022)
...
Other fields for drivetrain, engine etc
...
# Fields for individual car in database
id = models.UUIDField(primary_key=True, default=uuid.uuid4, help_text="Automatically generated unique ID. Do not change.")
mileage = models.IntegerField(null=True)
insurance = models.ForeignKey(Insurance, on_delete=models.RESTRICT, null=True)
daily_rate = models.IntegerField(default=3500, help_text="Daily rate in Kenyan Shillings")
def __str__(self):
return f'{ self.manufacturer } { self.model }'
@property
def insurance_expired(self):
"""Determines if insurance is expired based on due date and current date."""
return bool(self.insurance.expiry_date and datetime.date.today() > self.insurance.expiry_date)
class Meta:
ordering = []
permissions = (("can_change_availability", "Set car as rented"),)
def get_absolute_url(self):
return reverse('rental:car-detail', args=[str(self.id)])
urls.py
from django.urls import path, include
from . import views
app_name = 'rental'
# API endpoints
urlpatterns = [
path('', views.IndexView.as_view(), name='index'),
path('cars/', views.CarListView.as_view(), name='car-list'),
path('car/<uuid:id>', views.CarDetailView.as_view(), name='car-detail'),
]
Код ошибки
AttributeError at /rentals/car/43c9b98d-9f2d-473f-9c34-7b2e25630278
'CarDetailView' object has no attribute '_meta'
Request Method: GET
Request URL: http://localhost:8000/rentals/car/43c9b98d-9f2d-473f-9c34-7b2e25630278
Django Version: 4.1.3
Exception Type: AttributeError
Exception Value:
'CarDetailView' object has no attribute '_meta'
Обычно вы должны не реализовывать метод get()
самостоятельно, обычно это задача представлений Django (API), которые затем передадут его нужному рендереру и шаблону. Вы
class CarDetailView(generics.RetrieveAPIView):
renderer_classes = [TemplateHTMLRenderer]
template_name = 'car-detail.html'
serializer_class = CarSerializer
queryset = Car.objects.all()
В шаблоне вы можете затем использовать поля автомобиля, таким образом: {{ url }}
, {{ model }}
, {{ owner }}
и т.д.
Если вы планируете выводить шаблон, возможно, имеет смысл работать с DetailView
[Django-doc] вместо этого:
from django.views.generic.detail import DetailView
class CarDetailView(DetailView):
model = Car
template_name = 'car-detail.html'
в шаблоне, вы можете затем использовать {{ object.url }}
, {{ object.model }}
и т.д., а также "следовать" отношениям.