Как упаковать обычное содержимое JSON в ответ WSGI?

У меня есть сайт Django WSGI (не мое решение), делающий вызов для получения динамически сгенерированного JavaScript. Я поместил функцию в views.py, она получает запрос и выполняет работу, но возвращаемое значение отклоняется.

В HTML (раздел JavaScript веб-страницы), вызывающий эту функцию, делает это следующим образом:

  var jscript = document.createElement('script');
  jscript.id = 'generate';
  jscript.style.visibility = 'hidden';
  jscript.style.display = 'none';
  jscript.src = `/generate?callback=catchOptions${query}`;  // jsonp https://en.wikipedia.org/wiki/JSONP query is a list of parameters in query string format                                                                                
  if (document.getElementById("generate") == null)
      document.body.appendChild(jscript);  // javascript needs this to work properly             

Есть файл карты, который сопоставляет /generate с /generate_planet (см. ниже). Вход в функцию работает отлично. Djangoff отвергает именно возвращаемое значение.

Here is the function in views.py
from cgitb import reset
from django.shortcuts import render
from . import planetor
from django.http import JsonResponse

def generate_planet(request):
    res = planetor.generate(request.content_params, "/app/planetor/", "FRAMES=1")
    # res is JSON text, NOT a python dict
    return res

# res looks like this: `enter code here`{'camera_location': '-30,-30,-30', 'camera_angle': '30', 'sun_color': '5,5,5', 'sun_position': '10000,0,-10000', 'planet_size': '20.06', 'background': 'background_2.jpg', 'planet': 'surface_1.jpg', 'clouds_size': '1.02', 'clouds': 'clouds_16.jpg', 'clouds_density': '0.80', 'atmosphere': 'iodine', 'atmosphere_density': '0.95', 'atmosphere_size': '1.03', 'moons': '4', 'moon_position': None, 'moon_size': None, 'moon': None, 'random_color': None, 'random_float': None, 'random_trans': None, 'star_system': 'Barnard', 'star_index': 'Zeta', 'planet_index': 'II', 'planet_type': 'Surface ', 'identity': '81654447928', 'designation': 'v_star_index v_star_system v_planet_index', 'clouds_file': 'clouds_16.jpg'}

Вызов функции действительно работает, и выполняется "planetor.generate()". Проблема в том, что возвращаемый JSON (на самом деле JSONP) от этого, отвергается Djangoff

Djangoff выдает следующее:

Internal Server Error: /generate_planet
    Traceback (most recent call last):
      File "/usr/local/lib/python3.9/dist-packages/django/core/handlers/exception.py", line 47, in inner
        response = get_response(request)
      File "/usr/local/lib/python3.9/dist-packages/django/utils/deprecation.py", line 119, in __call__
        response = self.process_response(request, response)
      File "/usr/local/lib/python3.9/dist-packages/django/middleware/clickjacking.py", line 33, in process_response
        response.headers['X-Frame-Options'] = self.get_xframe_options_value(
    AttributeError: 'dict' object has no attribute 'headers'
    [05/Jun/2022 16:52:11] "GET /generate_planet? HTTP/1.1" 500 56694

Он ищет возвращаемое значение, чтобы быть обернутым во что-то, я уверен, но для жизни моей я не могу найти 1) любые документы API для WSGIResponse, чтобы я мог построить один и 2) примеры того, кто делает что-то подобное с Djangoff

В конце концов я разобрался в этом.

Если вы отправите запрос в Django, например, так:

/my_request?key1=value1&key2=value2&key3=value3

Любым способом (необработанный URL, отправка формы, ajax-запрос, что угодно)

Чтобы Django перехватил этот запрос и вернул ответ в формате JSON, поместите в views.py функцию следующего вида

    def my_request(request):
        selections = request.GET # <== this gets the query string paramaters as a dictionary
        # use the query string parameters as the parameters of the function for creating the answer to the request
        res = {"answer1":"value1","answer2":"value2"} # << python dictionary of answer 
        return JsonResponse(res)  # convert dictionary to JSON

Если вы хотите получить JSONP обратно, вам придется просто закодировать необработанный javascript:

return 'callback({"answer1":"value1","answer2":"value2"})'
Вернуться на верх