Django, разный результат между методом `all()` и методом `all().values()`.
Я столкнулся с проблемой, когда я не могу получить доступ к url некоторого изображения, используя метод values()
, но он все еще может быть доступен, если это объект queryset, а не pythonic list:
class MyModel(models.Model):
img = models.ImageField(upload_to='media') # the image is stored in aws, hence it will produce a url
def __str__(self):
return f"{self.img.url}"
это пример модели, теперь давайте попробуем распечатать это на shell:
>>models.MyModel.objects.all()
<QuerySet[{'img':'https://aws/bucketlist.com/some_img.png'}]>
однако с помощью метода values()
:
>>models.MyModel.objects.all().values()
<QuerySet[{'img':'media/some_img.png'}]>
как вы можете видеть values()
я получаю локальный путь, а не url к aws cloud
обратите внимание, что хранилище aws настроено правильно в django.
settings.py:
DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'
MEDIA_URL = '/media/'
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
CKEDITOR_UPLOAD_PATH = "/media"
AWS_ACCESS_KEY_ID = os.environ.get('AWS_ACCESS_KEY_ID')
AWS_SECRET_ACCESS_KEY = os.environ.get('AWS_SECRET_ACCESS_KEY')
AWS_STORAGE_BUCKET_NAME = os.environ.get('AWS_STORAGE_BUCKET_NAME')
AWS_S3_FILE_OVERWRITE = False
AWS_DEFAULT_ACL = None
DEFAULT_FILE_STORAGE = 'storages.backends.s3boto3.S3Boto3Storage'
AWS_S3_REGION_NAME = "ap-southeast-2"
AWS_S3_ADDRESSING_STYLE = "virtual"
Однако изображения появляются на AWS, и, похоже, все в порядке на стороне облака.
Это одна из мало причин не использовать .values()
в первую очередь: это сделает запрос к базе данных, а затем преобразует элементы в словари, и таким образом потеряет всю логику модели, привязанную к ней. Это означает, что .img
будет возвращать уже не объект FieldFile
, а простую строку, и, таким образом, покажет путь относительно корня медиа, а не весь URL, как это обычно делается через FieldFile
.
Ваш MyModelView
также вообще не работает с сериализатором: вы просто сделали реализацию get
, и поэтому в нем нет логики, которая работает с сериализатором.
Скорее всего, самый простой способ - просто работать с ListAPIView
[classy-drf]:
from rest_framework.generics import ListAPIView
class MyModelView(ListAPIView):
serializer_class = MyModelSerializer
queryset = models.MyModel.objects.all()
или вы можете использовать метод get_queryset
:
from rest_framework.generics import ListAPIView
class MyModelView(ListAPIView):
serializer_class = MyModelSerializer
queryset = models.MyModel.objects.all()
def get_queryset(self, *args, **kwargs):
data = MyModelSerializer(data=self.request.data)
if data.is_valid():
return super().get_queryset(*args, **kwargs).filter(data.data['name'])
return models.MyModel.objects.none()
def post(self, request):
return self.get(request)
Но обычно вы не используете POST-запросы для получения данных, а для создания, обновления или удаления данных. Обычно используется строка запроса для фильтрации набора запросов.