Как вывести порт после IP-адреса в URL ресурса в Django? - PullRequest
1 голос
/ 30 апреля 2019
  1. Как добавить порт узла к URL-адресам в моих сериализованных ответах? В настоящее время Django предоставляет их без порта, поэтому ссылки не работают.
  2. Или, если добавление порта не является правильным подходом, как мне изменить мою конфигурацию так, чтобы мне не нужно было указывать порт в URL при доступе к ресурсу?

Вывод (отсутствует порт ": 1337" в поле image_url)

{
    "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",

Подробнее

Stack:

  • Ubuntu
  • Докер (составь)
  • Nginx
  • Gunicorn 19.9.0
  • Джанго 2.1.7
  • Django REST Framework 3.9.2
  • Python 3 +
  • Postgres / psycopg2

Я использую Django REST framework для возврата списка сериализованных объектов. Объекты содержат FileField с именем «изображение», и я могу вывести URL этого изображения. Единственное, когда я нажимаю эту ссылку в выводе в своем браузере, я не могу получить доступ к ресурсу, не добавив вручную порт сервера в адрес, такой как

http://0.0.0.0:1337/mediafiles/publisher/sample-image4.jpg

Я не уверен, что это проблема nginx, проблема с настройками Django или просто как настроен мой код. У меня возникают проблемы с поиском других зарегистрированных случаев через Google (возможно, потому, что я все еще плохо знаком с Django и не уверен в правильной конфигурации, несмотря на следующие уроки).

Я попробовал некоторые из этих решений , но они не выводят порт.

Есть вопрос , но я не использую ImageField и хочу найти решение для случаев, когда я использую FileField. Комментарий к основному вопросу указывает на то, что добавление порта также не требуется, поэтому, возможно, это проблема инфраструктуры, а не проблема Django? Руководство по этому вопросу было бы замечательно.

models.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})

serializers.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

докер-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;
    }
}

1 Ответ

0 голосов
/ 22 мая 2019

Я наконец-то узнал, как исправить URL-адреса изображений благодаря этому вопросу , который немного отличается.

Решение 1

Добавьтеномер порта в заголовке хоста в конфигурации nginx следующим образом:

    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 на 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;
    }

В любом случае URL-адреса изображений теперь возвращаются DRF следующим образом ( ссылка на изображение ).

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"
        }
    ]
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...