Flask на примере-обновление пользовательского интерфейса (UI)

Flask на примере обновления пользовательского интерфейса

 

Ссылка на статью

Содержание:

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

Текущий пользовательский интерфейс

Запустите Redis в окне терминала:

$ redis-server

В другом окне запустите следующий код:

$ cd flask-by-example
$ python worker.py
17:11:39 RQ worker started, version 0.5.6
17:11:39
17:11:39 *** Listening on default...

Наконец, в третьем окне запустите приложение:

$ cd flask-by-example
$ python manage.py runserver

Протестируйте приложение, чтобы убедиться, что все работает. Вы должны увидеть примерно это:

Давайте внесем некоторые изменения.

1) Начнем с отключения кнопки "Отправить", чтобы пользователи не могли постоянно нажимать, ожидая подсчета от сайта.

2) Пока приложение подсчитывает слова, мы добавим дисплей загрузочной анимации. На него будет отправлен список подсчета слов, чтобы показать пользователю, что происходит активность в фоновом режиме.

3) Наконец, выведем ошибку, если домен не будет доступен.

Изменение кнопки

Измените кнопку в HTML на следующую:

{% raw %}
  <button type="submit" class="btn btn-primary"
  ng-disabled="loading">{{ submitButtonText }}</button>
{% endraw %}

Мы добавили директив ng-disabled и прикрепили его к loading. Это отключит кнопку, когда loading примет значения true. Затем мы добавили переменную для отображения пользователю под названием submitButtonText. Так мы сможем изменить текст с "Отправить" на "Загрузка...", чтобы пользователь знал, что происходит.

Затем мы завернули кнопку в {% raw %} и {% endraw%}, чтобы Jinja знал, что это необработанный HTML. Если бы мы этого не сделали, Flask попытался бы вычислить                      {{ submitButtonText }} как переменную Jinja, а Angular не удалось бы вычислить ее.

Дальнейший код на JavaScript довольно прост.

В верхней части WordcountController в main.js добавьте следующее:

$scope.submitButtonText = 'Submit';
$scope.loading = false;

Это установит исходное значение loading на false, чтобы кнопка не была отключена. Это также настроило текст кнопки на "Отправить".

Измените POST на:

$http.post('/start', {'url': userInput}).
  success(function(results) {
    $log.log(results);
    getWordCount(results);
    $scope.wordcounts = null;
    $scope.loading = true;
    $scope.submitButtonText = 'Loading...';
  }).
  error(function(error) {
    $log.log(error);
  });

Мы добавили три строки, которые задают…

1) wordcounts в значение null - чтобы старые значения очищались.

2) loading в значение true - чтобы кнопка "Загрузка..." была отключена с помощью директива ng-disabled, который мы добавили в HTML.

3) submitButtonText в значение "Загрузка..."- чтобы пользователь знал, почему кнопка отключена.

 

Затем обновите функцию poller:

var poller = function() {
  // fire another request
  $http.get('/results/'+jobID).
    success(function(data, status, headers, config) {
      if(status === 202) {
        $log.log(data, status);
      } else if (status === 200){
        $log.log(data);
        $scope.loading = false;
        $scope.submitButtonText = "Submit";
        $scope.wordcounts = data;
        $timeout.cancel(timeout);
        return false;
      }
      // continue to call the poller() function every 2 seconds
      // until the timeout is cancelled
      timeout = $timeout(poller, 2000);
    });
};

Когда результат будет успешным, мы вернем loading на false, чтобы кнопка снова была включена. И изменим текст кнопки обратно на "Отправить", чтобы пользователь знал, что может отправить новый URL-адрес.

Добавление анимационной загрузки

Далее давайте добавим анимационную загрузку под разделом подсчета слов, чтобы пользователь знал, что происходит. Это достигается путем добавления анимированного GIF-файла под div, как показано ниже:

<div class="col-sm-5 col-sm-offset-1">
  <h2>Frequencies</h2>
  <br>
  <div id="results">
    <table class="table table-striped">
      <thead>
        <tr>
          <th>Word</th>
          <th>Count</th>
        </tr>
      </thead>
      <tbody>
        {% raw %}
          <tr ng-repeat="(key, val) in wordcounts">
            <td>{{key}}</td>
            <td>{{val}}</td>            
          </tr>
        {% endraw %}
      </tbody>
    </table>
  </div>
  <img class="col-sm-3 col-sm-offset-4" src="{{ url_for('static',
  filename='spinner.gif') }}" ng-show="loading">
</div>

Возьмите spinner.gif по ссылке.

Вы можете увидеть, что ng-show прикреплен к loading точно так же как кнопка. Когда loading в значение true, отображается gif троббер. Когда loading в значение false (например, когда процесс подсчета слов заканчивается) - счетчик исчезает.

Работа над ошибками

Наконец, мы хотим разобраться со случаем, когда пользователь отправляет неверный URL-адрес. Начните с добавления следующего HTML-кода под формой:

<div class="alert alert-danger" role="alert" ng-show='urlerror'>
  <span class="glyphicon glyphicon-exclamation-sign" aria-hidden="true"></span>
  <span class="sr-only">Error:</span>
  <span>There was an error submitting your URL.<br>
  Please check to make sure it is valid before trying again.</span>
</div>

Здесь используется Bootstrap класс alert для отображения диалогового окна предупреждения, если пользователь отправляет неверный URL-адрес. Мы использовали директив Angular ng-show для отображения диалогового окна только в том случае, если urlerror в значение true.

Наконец, в WordcountController создайте $scope.urlerror в значение false, чтобы предупреждение изначально не появлялось:

$scope.urlerror = false;

Исправьте ошибки в функции poller:

var poller = function() {
  // fire another request
  $http.get('/results/'+jobID).
    success(function(data, status, headers, config) {
      if(status === 202) {
        $log.log(data, status);
      } else if (status === 200){
        $log.log(data);
        $scope.loading = false;
        $scope.submitButtonText = "Submit";
        $scope.wordcounts = data;
        $timeout.cancel(timeout);
        return false;
      }
      // continue to call the poller() function every 2 seconds
      // until the timeout is cancelled
      timeout = $timeout(poller, 2000);
    }).
    error(function(error) {
      $log.log(error);
      $scope.loading = false;
      $scope.submitButtonText = "Submit";
      $scope.urlerror = true;
    });
};

Это записало ошибку в консоль, изменило loading на false, вернуло текст кнопки на "Отправить", чтобы пользователь мог попробовать снова, и изменило urlerror на true, чтобы появилось предупреждение.

В заключение, в функции success для POST-вызова '/start' установите urlerror в значение false:

$scope.urlerror = false;

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

Flask на примере-обновление пользовательского интерфейса (UI): 1 комментарий

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *