Как передать kwargs из Python для обновления более одного столбца в SQL - PullRequest
0 голосов
/ 30 января 2019

Итак, у меня есть приложение, написанное на nodejs.В настоящее время, когда я создаю проблему, а затем редактирую ту же самую проблему, title_name и описание, название заголовка обновляется и отображается во внешнем интерфейсе, однако описание остается тем же и не обновляется.Я просматривал мой код на python и таблицу sql, но это выглядит хорошо, даже мой файл index.js.Он запустит оператор update для заголовка и обновит его, однако для описания он не будет.Пока у меня есть следующее:

Мои resources.py:

class IssueResource(object):
    def __init__(self, repo):
        self._repo = repo

    def on_get(self, req, resp, issue_id):
        with self._repo.open() as repo:
            issue = repo.issues.fetch_issue(int(issue_id))
            resp.media = _issue_to_json(issue)
            resp.status = falcon.HTTP_200

    def on_put(self, req, resp, issue_id):
        with self._repo.open() as repo:
            update = req.media
            repo.issues.update_issue(issue_id, **update)
            resp.status = falcon.HTTP_204

models.py

def fetch_issue(self, issue_id):
        cursor = self._conn.cursor()
        try:
            cursor.execute(
                """SELECT
                    id,
                    title,
                    description,
                    opened_datetime,
                    closed_datetime
                    FROM issues
                    WHERE id = {}""".format(issue_id))
            return make_issue(cursor.fetchone())
        finally:
            cursor.close()


def update_issue(self, issue_id, **kwargs):
        cursor = self._conn.cursor()
        try:
            if 'title' in kwargs:
                    cursor.execute(
                        """UPDATE issues SET title = '{}'  WHERE id = {}"""
                            .format(kwargs['title'], issue_id)
                    )
            if 'description' in kwargs:
                cursor.execute(
                    """UPDATE issues SET description = '{}' WHERE id = {}"""
                    .format(kwargs['description'], issue_id)
                )
            if 'closed' in kwargs:
                cursor.execute(
                    """UPDATE issues SET closed_datetime = '{}' WHERE id = {}"""
                    .format(kwargs['closed'].isoformat(), issue_id)
                )
        finally:
            cursor.close()

Это структура моей таблицы sql:

CREATE TABLE issues(
  id INTEGER PRIMARY KEY,
  title VARCHAR(255),
  description TEXT,
  opened_datetime CHAR(26) DEFAULT (datetime('now')),
  closed_datetime CHAR(26)
)

Мой внешний интерфейс моего приложения выглядит следующим образом: index.js - это то место, где установлена ​​вся моя маршрутизация:

require('babel-polyfill')
const m = require('mithril')
const {IssuesList, ViewIssue, CreateIssue, EditIssue, ToolbarContainer} = require('./views')
const {IssuesModel} = require('./viewmodels')

const issuesModel = new IssuesModel()

m.route(document.body, '/issues', {
  '/issues': {
    render(vnode) {
      return m(ToolbarContainer, m(IssuesList, {model: issuesModel}))
    }
  },
  '/issues/create': {
    render(vnode) {
      return m(ToolbarContainer, m(CreateIssue, {model: issuesModel}))
    }
  },

  '/issues/:issueId/edit': {
    render(vnode) {
      return m(ToolbarContainer, m(EditIssue, {model: issuesModel, issueId: vnode.attrs.issueId}))
    }
  }
})

view.js - это все представления каждогодругая страница:

const m = require('mithril')

class IssuesList {
  constructor(vnode) {
    this.model = vnode.attrs.model
  }
  oninit() {
    this.model.loadIssues()
  }
  view() {
    return m('table.table', [
      m('thead', [
        m('th', 'title'),
        m('th', 'opened'),
        m('th', 'closed')
      ]),
      m('tbody', [
        this.model.list.map(item =>
          m('tr', [
            m('td.title-cell', m("a", {href: `/issues/${item.id}`, oncreate: m.route.link}, item.title)),
            m('td.opened-cell', item.opened),
            m('td.closed-cell', item.closed)
          ])
        )
      ])
    ])
  }
}

class ViewIssue {
  constructor(vnode) {
    this.model = vnode.attrs.model
    this.issueId = vnode.attrs.issueId
  }
  oninit() {
    this.model.loadIssue(this.issueId)
  }
  view() {
    let detail = this.model.issues[this.issueId]
    return detail
    ? m('div',[
        m('.row', [
          m('h1.col-sm-11', detail.title),
          m('.col-sm-1',
            m(
              'a.btn.btn-primary',
              {href: `/issues/${this.issueId}/edit`, oncreate: m.route.link},
              'Edit'
            )
          )
        ]),
        m('dl.row', [
          m('dt.col-sm-3', 'Opened'),
          m('dd.col-sm-3', detail.opened),
          m('dt.col-sm-3', 'Closed'),
          m('dd.col-sm-3', detail.closed),
        ]),
        m('h2', 'Description'),
        m('p.description', detail.description)
      ]
    )
    : m('.alert.alert-info', 'Loading')
  }
}

class EditIssue {
  constructor(vnode) {
    this.model = vnode.attrs.model
    this.issueId = vnode.attrs.issueId
  }
  async oninit() {
    await this.model.loadIssue(this.issueId)
  }
  view() {
    let issue = this.model.issues[this.issueId]
    return issue
    ? m(IssueEditor, {
      title: issue.title,
      descriptionText: issue.description,

      onSubmit: async (fields) => {
        await this.model.updateIssue(this.issueId, fields)
        m.route.set(`/issues/${this.issueId}`)
        m.redraw()
      }
    })
    :m('.alert.alert-info', 'Loading')

  }
}

class CreateIssue {
  constructor(vnode) {
    this.model = vnode.attrs.model
  }
  view() {
    return m(IssueEditor, {
      title: '',
      descriptionText: '',
      onSubmit: async ({descriptionText, title}) => {
        await this.model.createIssue({description: descriptionText, title: title})
        m.route.set(`/issues`)
        m.redraw()
      }
    })
  }
}

class IssueEditor {
  constructor(vnode) {
    this.title = vnode.attrs.title
    this.descriptionText = vnode.attrs.descriptionText
    this.onSubmit = vnode.attrs.onSubmit
  }
  view() {
    return m('form', {onsubmit: e => this.onSubmit({title: this.title, descriptionText: this.descriptionText})}, [
      m('.form-group', [
        m('label', {'for': 'title-input'}, 'Issue Title'),
        m('input.form-control#title-input', {value: this.title, oninput: (e) => {this.title = e.target.value}})
      ]),
      m('.form-group', [
        m('label', {'for': 'description-input'}, 'Description'),
        m('textarea.form-control#description-input', {oninput: (e) => {this.descriptionText = e.target.value}}, this.descriptionText)
      ]),
      m('button.btn.btn-primary#save-button', {type: 'submit'}, 'Save')

    ])
  }
}


module.exports = {IssuesList, ViewIssue, EditIssue, CreateIssue, IssueEditor}

Основной скрипт для запуска приложения python:

from __future__ import absolute_import
import argparse
import falcon
import os

from .resources import IssueResource, IssuesResource
from .models import Repository


def _index_middleware(app):
    def handler(environ, start_response):
        if environ['PATH_INFO'] == '/':
            environ['PATH_INFO'] = '/index.html'
        return app(environ, start_response)
    return handler


def make_api(database_location, migrate_database=True):
    api = falcon.API()
    repo = Repository(database_location)
    if migrate_database:
        repo.migrate_database()
    api.add_route('/issues', IssuesResource(repo))
    api.add_route('/issues/{issue_id}', IssueResource(repo))
    static_dir = os.path.abspath(os.path.join(__file__, '..', '..', 'dist'))
    api.add_static_route('/', static_dir)
    return _index_middleware(api)


if __name__ == '__main__':
    from werkzeug.serving import make_server

    parser = argparse.ArgumentParser(description="Run a bug tracker server")
    parser.add_argument('--interface', default='0.0.0.0',
                        help="Interface to bind to")
    parser.add_argument('--port', default=8640,
                        help="Port to listen on")
    parser.add_argument('--database-location',
                        default=os.path.join(
                            os.path.dirname(__file__), '..', 'database.db'
                        ), help="Where to store the database")
    parser.add_argument('--no-database-migrations', action='store_true',
                        help="Do not perform database migrations")
    parser.add_argument('--clean', action='store_true',
                        help="Delete the database and start from clean")
    args = parser.parse_args()
    if args.clean:
        os.remove(args.database_location)

    api = make_api(args.database_location, not args.no_database_migrations)
    httpd = make_server(args.interface, args.port, api)
    print "Serving on {args.interface}:{args.port}".format(args=args)
    httpd.serve_forever()
...