输出(image_url 字段中缺少端口“:1337”)
{
"count": 1,
"next": null,
"previous": null,
"results": [
{
"id": 1,
"user": 1,
"title": "Post 1",
"slug": "post1",
"image_url": "http://0.0.0.0/mediafiles/publisher/sample-image4.jpg",
"content": "First",
"draft": false,
"publish": "2019-04-26",
"updated": "2019-04-26T22:28:35.034742Z",
"timestamp": "2019-04-26T22:28:35.034795Z"
}
]
}
“image_url”字段将无法正确链接,除非它包含如下端口:
"image_url": "http://0.0.0.0:1337/mediafiles/publisher/sample-image4.jpg",
堆栈:
我正在使用 Django REST 框架返回序列化对象的列表。这些对象包含一个名为“image”的 FileField,我可以输出该图像的 URL。唯一的问题是,当我在浏览器的输出中单击该链接时,如果不手动在地址中添加服务器端口,则无法访问该资源,例如
http://0.0.0.0:1337/mediafiles/publisher/sample-image4.jpg
我不确定这是 nginx 问题、Django 设置问题还是我的代码配置方式问题。我无法通过 Google 找到任何其他报告的案例(可能是因为我对 Django 还很陌生,尽管有以下教程,但不确定配置是否正确)。
我尝试了一些这些解决方案,但它们不输出端口。
有这个问题,但我没有使用 ImageField,我想为我使用 FileField 的情况找到解决方案。对主要问题的评论表明也不需要添加端口,所以也许这是一个基础设施问题而不是 Django 问题?对此的指导会很棒。
模型.py
class Post(models.Model):
class Meta:
ordering = ('timestamp',)
user = models.ForeignKey(User, on_delete=models.PROTECT)
title = models.CharField(max_length=120)
slug = models.SlugField(unique=True)
image = models.FileField(upload_to='publisher/', null=True, blank=True)
content = models.TextField()
draft = models.BooleanField(default=False)
publish = models.DateField(auto_now=False, auto_now_add=False)
updated = models.DateTimeField(auto_now=True, auto_now_add=False)
timestamp = models.DateTimeField(auto_now=False, auto_now_add=True)
def __str__(self):
return self.title
def __unicode__(self):
return str(self.id)
def get_absolute_url(self):
return reverse("post:detail", kwargs={"slug":self.slug})
序列化器.py
class PostSerializer(serializers.ModelSerializer):
image_url = serializers.SerializerMethodField()
class Meta:
model = Post
fields = [
'id',
'user',
'title',
'slug',
'image_url',
'content',
'draft',
'publish',
'updated',
'timestamp',
]
def get_image_url(self, post):
request = self.context.get('request')
if post.image and hasattr(post.image, 'url'):
image_url = post.image.url
return request.build_absolute_uri(image_url)
else:
return None
urls.py
urlpatterns = [
path('admin/', admin.site.urls),
re_path('blog/(?P<version>(v1|v2))/', include('blog.urls'))
]
...
[
url(r'^posts/$', PostListAPIView.as_view(), name='posts'),
]
if settings.DEBUG:
urlpatterns += static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)
urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
views.py
class PostListAPIView(generics.ListAPIView):
model = Post
queryset = Post.objects.all()
serializer_class = PostSerializer
docker-compose.yml
version: '3.7'
services:
web:
build: ./app
command: gunicorn hello_django.wsgi:application --bind 0.0.0.0:8000
volumes:
- ./app/:/usr/src/app/
- static_volume:/usr/src/app/staticfiles
- media_volume:/usr/src/app/mediafiles
ports:
- "8000"
env_file: ./app/.env
environment:
- DB_ENGINE=django.db.backends.postgresql
- DB_USER
- DB_PASSWORD
- DB_HOST=db
- DB_PORT=5432
- DATABASE=postgres
depends_on:
- db
networks:
- backend
db:
image: postgres:10.7-alpine
ports:
- "5432:5432"
volumes:
- postgres_data:/var/lib/postgresql/data/
networks:
- backend
nginx:
build: ./nginx
volumes:
- static_volume:/usr/src/app/staticfiles
- media_volume:/usr/src/app/mediafiles
ports:
- "1337:80"
depends_on:
- web
networks:
- backend
networks:
backend:
driver: bridge
volumes:
postgres_data:
static_volume:
media_volume:
nginx.conf
upstream hello_django {
server web:8000;
}
server {
listen 80;
location / {
proxy_pass http://hello_django;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $host;
proxy_redirect off;
}
location /staticfiles/ {
alias /usr/src/app/staticfiles/;
}
location /mediafiles/ {
alias /usr/src/app/mediafiles/;
}
location /favicon.ico {
access_log off;
log_not_found off;
}
}
我终于找到了如何修复图像 URL,这要归功于 this Question,它略有不同。
解决方案1
在 nginx 配置的 Host 标头中添加端口号,如下所示:
location / {
proxy_pass http://hello_django;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $host:1337; <<------- HERE
proxy_redirect off;
}
解决方案2
将 nginx 配置中的 Host 标头更改为
http_host
,如下所示:
location / {
proxy_pass http://hello_django;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host; <<------- HERE
proxy_redirect off;
}
无论哪种情况,DRF 现在都会按如下方式返回图像 URL(图像链接)。
HTTP 200 OK
Allow: GET, HEAD, OPTIONS
Content-Type: application/json
Vary: Accept
{
"count": 1,
"next": null,
"previous": null,
"results": [
{
"id": 2,
"user": 1,
"title": "First post",
"slug": "first",
"image_url": "http://0.0.0.0:1337/mediafiles/publisher/background.gif", <----HERE
"content": "Second post content.",
"draft": false,
"publish": "2019-05-22",
"updated": "2019-05-22T09:41:36.257605Z",
"timestamp": "2019-05-22T07:58:01.471534Z"
}
]
}
添加:
proxy_set_header Host $host:1337;
为我工作