Обновление и сохранение dict в django с почтовыми запросами - PullRequest
0 голосов
/ 09 апреля 2020

Я пытаюсь создать адаптивную турнирную скобку с помощью python / django и использую запросы $ .post для обновления турнирной информации - которую я передаю шаблону «скобок» в виде словаря, рендеринга, а затем обновления на $. отправка переданной переменной в другое представление, которое обновляется, сохраняется на сервере, а затем перенаправляется в представление «скобок».

Я только начинаю добиваться определенного прогресса, но у меня возникают проблемы с переформатированием объекта скобок.

Немного больше деталей

Скобка инициализируется в python (в моем views.py) в представлении скобки, но я вызываю в представлении турнир класс, который я получил от здесь .

класс Турнира берет список игроков и затем генерирует словарь, соответствующий играм, с помощью метода t.generate_bracket ().

Я как бы реструктурирую это, а затем передаю в скобки для отображения - я отображаю реструктурированный массив в своем шаблоне, но также передаю нереструктурированный

I есть маленькие переключатели, которые связаны с представлением $ .post 'update_bracket'. В JS $ .post я отправляю массив в представление, где я буду вызывать метод t.play_game () для обновления скобки. Затем - вместо ответа JSON или HTTP и последующего повторного заполнения клиентской части скобок (что я недостаточно хорош во внешнем интерфейсе), я сохраняю обновленную скобку в JSONField на модели сотрудника (расширяет зарегистрированную запись). в user) и HTTPResponseRedirect к начальному представлению «скобки», где у меня есть проверка, чтобы увидеть, есть ли у сохраненного в них скобка сотрудника, а затем использовать это значение, сохраненное в JSONField, как новую скобку, которая будет отображаться - вместо генерации с нуля с помощью t.generate_bracket ()

Вот мое представление скобок, мое представление обновлений, скобки. html с json $ .post () для update_bracket и некоторыми из турниров и других классов. Я использую

Код

Исходный вид скобки

@login_required#(login_url='/accounts/login/')
def bracket(request):
    '''

    :param request:
    :return:
    '''

    emp = Employee.objects.get(user = request.user)
    emp_bracket = emp.guess

    players = [p.id for p in Pet.objects.all()]
    t = Tournament(players)
    if not emp_bracket:
        t.generate_bracket('single', 0)
    else:
        t.games = emp_bracket
    tournament_games = t.games

    nested_tournament_games = {}
    nested_tournament_games['rounds']={}


    for g_id,g in tournament_games.items():
        #....I do restructuring of the tournament_games dict

    context = {'arr':tournament_games, 'nested':nested_tournament_games['rounds']}#{'latest_question_list': latest_question_list}
    return render(request, 'madness/bracket.html', context)

.пост в шаблоне скобки

$('input[type=radio][name=bStatus]').change(function() {
alert(this.value);

$.post('{% url "update_bracket"  %}',
        { bracketData: JSON.stringify("{{arr}}") },
        function(data, status, xhr) {
console.log(JSON.stringify(data));
var nested = JSON.stringify(data);
        }).done(function() {  })
        .fail(function(jqxhr, settings, ex) { alert('failed, ' + ex); });
});

update_bracket view

@csrf_exempt
def update_bracket(request):
    bracketData = request.POST['bracketData']
    print(json.loads(bracketData))

    #I plan on using the play_game() method here, but first I have to just get the basics down

    emp = Employee.objects.get(user = request.user)
    emp.guess = bracketData
    emp.save()
    # return HttpResponse(json.loads(bracketData))
    return HttpResponseRedirect(reverse('bracket'))

Турнирный класс, которым я пользуюсь

class Tournament:
    def __init__(self, players):
        self.players = players
        self.player_count = len(players)
        self.games = {}

...


    def generate_bracket(self, bracket_class, randomize):
        if bracket_class != "single":
            print("Illegal bracket class")
            quit()

        self.n_size = int(math.ceil(math.log(self.player_count, 2)))
        self.underflow = int(math.pow(2, self.n_size) - self.player_count)

        if randomize:
            random.shuffle(self.players)

        for i in range(self.underflow):
            self.players.append(None)

        self.num_of_rounds = int(math.log(len(self.players), 2))

        self.games = generate_bracket_rec(self.players, self.num_of_rounds)


...

def generate_bracket_rec(players, num_of_rounds):
    games_map = {}
    next_players = []

    assert len(players) > 0

    if len(players) == 1:
        return games_map

    gm=1
    for i in range(int(len(players) / 2)):
        player1_id = i
        player2_id = len(players) - 1 - i

        if players[player2_id] is None:
            next_players.append(players[player1_id])
        else:
            round=str(1+num_of_rounds-int(math.log(len(players), 2)))
            game_id = "round_"+round + "_game_" + str(gm)#str(i + 1)
            g = Game((players[player1_id], players[player2_id]), game_id)
            g.round, g.game = round, gm
            games_map[g.id] = g#{'players':g.players, 'winner':g.winner, 'loser':g.loser, 'done':g.done}
            # next_players.append((g, "winner"))  #the winner of that game
            # next_players.append('winner of %s and %s' % (g.players))
            next_players.append('winner of Round %s Game %s' % (g.round, g.game))

            gm += 1
    d = {}
    d.update(games_map)
    d.update(generate_bracket_rec(next_players, num_of_rounds).items())
    return d

Ошибки в форматировании

Я пробовал разные способы работы с турнирным объектом JSON, так как сейчас он стоит, ошибка, с которой я сталкиваюсь в js в $ .post - Uncaught SyntaxError: неверный или неожиданный токен, поэтому код даже не достигает update_bracket view.

DevTools показывает

$.post('/update_bracket',
        { bracketData: JSON.stringify("{'round_1_game_1': round_1_game_1: 2 vs 3
Done: False, 'round_2_game_1': round_2_game_1: 1 vs winner of Round 1 Game 1
Done: False}") },

Кто-нибудь знает, как мне нужно иметь дело с этим объектом турнира в жизненном цикле

python (генерируется как dict) - -> шаблон (переданный в качестве контекста var) -> python (из .post этого переданного в template-var) -> сохранить в django JSONField -> полученный из JSONField (перезапуск цикла)

РЕДАКТИРОВАТЬ - JSON Ошибка декодирования

После следующих советов о том, что делать с передачей в шаблон, я получаю новую ошибку в update_bracket. Я могу отправить данные туда, но затем, когда я пытаюсь загрузить (), я получаю ошибку JSONDecode. Вы знаете, как я могу справиться с этим?

request.POST['bracketData']
'{"round_1_game_1": {"players": [2, 3], "winner": null, "loser": null, "done": false}, "round_2_game_1": {"players": [1, "winner of Round 1 Game 1"], "winner": null, "loser": null, "done": false}}'
json.loads(request.POST['bracketData'])
Traceback (most recent call last):
  File "C:\Program Files\JetBrains\PyCharm Community Edition 2019.2.1\helpers\pydev\_pydevd_bundle\pydevd_exec2.py", line 3, in Exec
    exec(exp, global_vars, local_vars)
  File "<input>", line 1, in <module>
  File "C:\Users\aiden\AppData\Local\Programs\Python\Python37-32\lib\json\__init__.py", line 348, in loads
    return _default_decoder.decode(s)
  File "C:\Users\aiden\AppData\Local\Programs\Python\Python37-32\lib\json\decoder.py", line 337, in decode
    obj, end = self.raw_decode(s, idx=_w(s, 0).end())
  File "C:\Users\aiden\AppData\Local\Programs\Python\Python37-32\lib\json\decoder.py", line 353, in raw_decode
    obj, end = self.scan_once(s, idx)
json.decoder.JSONDecodeError: Expecting property name enclosed in double quotes: line 1 column 2 (char 1)


1 Ответ

1 голос
/ 09 апреля 2020

Когда вы делаете {{ arr }} в своем шаблоне, вы просто указываете python напечатать объект arr в виде строки. Поскольку arr является словарем (это tournament_games), вы печатаете что-то вроде {'key': 'value'}, которое не является строкой JSON (JSON строки нуждаются в двойных кавычках ").

И затем вы оборачиваете это в "", превращая его в javascript строку, и ваши javascript вызывают JSON.stringify() на нем. Но это не работает, потому что stringify() ожидает объект javascript, а не строку.

Поскольку все, что вам нужно, это опубликовать строку JSON, создайте эту строку в python и напечатайте ее в вашем шаблоне. В вашем контексте:

'arr': json.dumps(tournament_games)

и в вашем шаблоне:

bracketData: "{{ arr }}"
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...