Python Flask Упорядоченный словарь преобразуется в строку - PullRequest
0 голосов
/ 03 марта 2020

Я написал веб-сервер и у меня возникли проблемы с удалением задач с помощью функции bulkdelete.

В функции удаления заданий есть список OrderedDicts. Однако в функции bulkdelete вместо OrderedDict возвращается строка типа, которую я не понимаю. Конвертируется ли контент и как я могу получить доступ к задачам [count] ["id"] в функции bulkdelete? В настоящее время он возвращает

TypeError: string indices must be integers, not str

Здесь вы можете увидеть весь мой код:

from flask import Flask, request, Response
import json
app = Flask(__name__)
from collections import OrderedDict
tasks=[]

# Create a new task
@app.route('/v1/tasks', methods=['POST'])
def post():
    data = request.get_json()
    if "title" not in data:
        return bulkadd(data)
    completed=False
    if "is_completed" in data:
        completed=data["is_completed"]
    title = data["title"]
    tasks.append(OrderedDict((
        ('id', len(tasks) + 1),
        ('title', title),
        ('is_completed', completed),
    )))
    index = len(tasks)
    return json.dumps({"id": index}), 201


#List all tasks created
@app.route('/v1/tasks', methods=['GET'])
def getall():
   print(json.dumps({"tasks": tasks}))
   return json.dumps({"tasks": tasks}), 200

#Get a specific task
@app.route('/v1/tasks/<id>', methods=['GET'])
def getone(id):
    #This is wrong if one id is deleted and afterwards another one get
    i=0
    while i < len(tasks):
        if tasks[i]["id"]==int(id):
            return tasks[i], 200
        i=i+1
    return json.dumps({"error": "There is no task at that id"}), 404

#Delete a specific task
@app.route('/v1/tasks/<id>', methods=['DELETE'])
def delete(id):
    #loop that iterates through the list, searches for "id" in each dict and if they match, the dict is deleted
    i=0
    print(type(tasks))
    print(type(tasks[i]))
    while i < len(tasks):
        if tasks[i]["id"]==int(id):
            del tasks[i-1]
    return Response(status=204)

#(Extra Credit) Bulk delete tasks
@app.route('/v1/tasks/', methods=['DELETE'])
def bulkdelete():
    data=request.get_json()
    ids=data["tasks"]
    cleaned_ids=[]
    i = 0
    #print(tasks)
    while i < len(ids):
        cleaned_ids.append(ids[i]["id"])
        i=i+1
    print(cleaned_ids)
    for id in cleaned_ids:
        count=0
        while count < len(tasks):
            print(tasks[count])
            print(type(tasks[count]))
            if tasks[count]["id"] == id:
                print("delete")
                del tasks[count]
            count=count+1
    print(tasks)
    return Response(status=204)

#Edit the title or completion of a specific task
@app.route('/v1/tasks/<int:id>', methods=['PUT'])
def edit(id):
    data=request.get_json()
    i=0
    while i < len(tasks):
        if tasks[i]["id"] == id:
            tasks[i]["title"]=data["title"]
            tasks[i]["is_completed"]=data["is_completed"]
            return Response(status=204)
        i=i+1
    return json.dumps({"error": "There is no task at that id"}), 404

#(Extra Credit) Bulk add tasks
def bulkadd(data):
    content=data["tasks"]
    output=[]
    i=0
    while i < len(content):
        tasks.append(json.dumps({"id": len(tasks)+1, "title": content[i].get("title"), "is_completed": content[i].get("is_completed")}))
        output.append({"id": len(tasks)})
        i=i+1
    return json.dumps({"tasks": output}), 201

Вы можете использовать этот код для тестирования:

import requests
import json

def test_create_task():
    r = requests.post('http://localhost:5000/v1/tasks', json={"title": "My First Task"})
    assert isinstance(r.json()["id"], int)
    assert len(r.json()) == 1

def test_list_all_tasks():
    r = requests.get('http://localhost:5000/v1/tasks')
    assert isinstance(r.json()["tasks"], list)
    assert len(r.json()) == 1
    print(r.json())
    print(r.json()["tasks"][0]["id"])
    assert isinstance(r.json()["tasks"][0]["id"], int)
    assert isinstance(r.json()["tasks"][0]["title"], str)
    assert isinstance(r.json()["tasks"][0]["is_completed"], bool)
    assert len(r.json()["tasks"][0]) == 3

def test_get_task():
    r = requests.get('http://localhost:5000/v1/tasks/1')
    assert isinstance(r.json(),dict)
    assert isinstance(r.json()["id"], int)
    assert isinstance(r.json()["title"], str)
    assert isinstance(r.json()["is_completed"], bool)
    assert len(r.json()) == 3

def test_update_task():
    r = requests.put('http://localhost:5000/v1/tasks/1', json={'title': "Test Task 2", 'is_completed': 'false'})
    print(r.content)
    assert not r.content

def test_delete_task():
    r = requests.delete('http://localhost:5000/v1/tasks/1')
    assert not r.content

def test_add_bulk_task():
    r = requests.post('http://localhost:5000/v1/tasks', json={
   "tasks": [
      {"title": "Test Task 1", "is_completed": "true"},
      {"title": "Test Task 2", "is_completed": "false"},
      {"title": "Test Task 3", "is_completed": "true"}
   ]
})
    print(r)
    assert isinstance(r.json()["tasks"][0]["id"], int)
    assert len(r.json()) == 1

def test_delete_bulk_task():
    r = requests.delete('http://localhost:5000/v1/tasks/', json={
   "tasks": [
     {"id": 1},
     {"id": 2},
     {"id": 3}
  ]
})
    print(r)
    assert not r.content

Спасибо за ваш помощь!

Ответы [ 2 ]

2 голосов
/ 03 марта 2020

Проблема в том, что ваши задачи [i] - это словарь, но в строковом формате. После отладки вашего кода я получил эту первую строку в момент ошибки: (вторая строка - это то, что вы хотите, чтобы задачи [i] были, обратите внимание, что первая строка - это не слово) enter image description here

Проблема заключается в функции bulkadd и, возможно, в других имеющихся у вас функциях добавления. Когда вы используете jsom.dumps ({"key": "val"}), он создаст строку в формате dict, например: '{"key": "val"}'

Я считаю, что проблема в Функция bulkadd (и другие функции добавления) при использовании json .dumps при добавлении в список задач. Поэтому, если вы удалите main.dumps при добавлении, это решит проблему, но вы можете сохранить возврат json .dumps () в качестве ответа для приложения flask. При выполнении этой задачи [I] будет диктом, а не строковым форматированием dict

def bulkadd(data):
    content=data["tasks"]
    output=[]
    i=0
    while i < len(content):
        tasks.append(json.dumps({"id": len(tasks)+1, "title": content[i].get("title"), "is_completed": content[i].get("is_completed")}))
        output.append({"id": len(tasks)})
        i=i+1
    return json.dumps({"tasks": output}), 201
def bulkadd(data):
    content=data["tasks"]
    output=[]
    i=0
    while i < len(content):
        tasks.append({"id": len(tasks)+1, "title": content[i].get("title"), "is_completed": content[i].get("is_completed")})
        output.append({"id": len(tasks)})
        i=i+1
    return json.dumps({"tasks": output}), 201
0 голосов
/ 03 марта 2020

Прежде чем разобраться в вашей проблеме, у меня есть пара замечаний к вашему коду. Я бы сохранял задачи в словаре для облегчения последующего удаления, вместо того, чтобы хранить диктовки в списке, как сейчас.

задачи будут выглядеть так:

tasks = {1: {'title': 'test', 'is_completed': False}, 2 : {'title': 'test2', 'is_completed': True}

Улучшенный метод массового удаления будет выглядеть так:

data=request.get_json()
for task in data['tasks']:
    del tasks[task['id']]
return Response(status=204)

Использование всех циклов while и счетчиков не действительно pythoni c и заставляет вас иметь более длинный код, который подвержен ошибкам.

Я надеюсь, что вы сможете улучшить другие части своего кода, следуя моему примеру, и если вам понадобится дополнительная помощь, держите нас в курсе!

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