如何集成python脚本模块并在html

时间:2019-07-10 10:53:03

标签: django python-3.x module external-script

我是django和python的新手。 我想执行一个python脚本(而不是来自views.py),并将结果显示为HTML文件作为输出。

问题出在模块上。 python脚本getoffense.py使用三个模块。

我尝试运行该脚本,但是它在下面给了我模块导入错误。我已经将模块保存在主应用程序“ Project1”中的目录“ modules”中 python脚本在我的主项目即Project1中。

当我运行getoffense.py时,我导入的模块将间接运行。

这是我的项目树。

C:.
├───.idea
└───project1
    ├───modules
    │   └───__pycache__
    ├───templates
    └───__pycache__

当未与django集成时,文件结构为

scripts
|--modules
     |--RestApiClient.py
     |--config.py
     |--SampleUtilities.py
|--siem
    |-getoffense.py
|--config(type=configuration settings)

单独执行时效果很好

我尝试在Django项目中以视图形式执行文件。 请帮助我摆脱这个问题。

我已经尝试像对views.py一样进行集成,并在home.html中显示数据

getoffense.py

from django.shortcuts import render


import importlib
sys.path.append(os.path.realpath('./modules'))
client_module = importlib.import_module('./modules/RestApiClient')
SampleUtilities = importlib.import_module('./modules/SampleUtilities')



def getalloffense(request):

    # First we have to create our client
    client = client_module.RestApiClient(version='9.0')

    # -------------------------------------------------------------------------
    # Basic 'GET'
    # In this example we'll be using the GET endpoint of siem/offenses without
    # any parameters. This will print absolutely everything it can find, every
    # parameter of every offense.

    # Send in the request
    SampleUtilities.pretty_print_request(client, 'siem/offenses', 'GET')
    response = client.call_api('siem/offenses', 'GET')

    # Check if the success code was returned to ensure the call to the API was
    # successful.
    if (response.code != 200):
        print('Failed to retrieve the list of offenses')
        SampleUtilities.pretty_print_response(response)
        sys.exit(1)

    # Since the previous call had no parameters and response has a lot of text,
    # we'll just print out the number of offenses
    response_body = json.loads(response.read().decode('utf-8'))
    print('Number of offenses retrieved: ' + str(len(response_body)))

    # -------------------------------------------------------------------------
    # Using the fields parameter with 'GET'
    # If you just print out the result of a call to the siem/offenses GET
    # endpoint there will be a lot of fields displayed which you have no
    # interest in. Here, the fields parameter will make sure the only the
    # fields you want are displayed for each offense.

    # Setting a variable for all the fields that are to be displayed
    fields = '''id%2Cstatus%2Cdescription%2Coffense_type%2Coffense_source%2Cmagnitude%2Csource_network%2Cdestination_networks%2Cassigned_to'''

    # Send in the request
    SampleUtilities.pretty_print_request(client, 'siem/offenses?fields='+fields, 'GET')
    response = client.call_api('siem/offenses?fields=' +fields, 'GET')


    # Once again, check the response code
    if (response.code != 200):
        print('Failed to retrieve list of offenses')
        SampleUtilities.pretty_print_response(response)
        sys.exit(1)

    # This time we will print out the data itself
    #SampleUtilities.pretty_print_response(response)

    response_body = json.loads(response.read().decode('utf-8'))
    print(response_body)
    print(type(response_body))
    for i in response_body:
        print(i)
        print("")

    for j in response_body:
        print(j['id'])
        print(j['status'])
        print(j['description'])

    return render(request, 'home.html', response_body)

RestApiClient.py

from config import Config

from urllib.error import HTTPError
from urllib.error import URLError
from urllib.parse import quote
from urllib.request import Request
from urllib.request import urlopen
from urllib.request import install_opener
from urllib.request import build_opener
from urllib.request import HTTPSHandler

import SampleUtilities

import ssl
import sys
import base64


# This is a simple HTTP client that can be used to access the REST API
class RestApiClient:

    # Constructor for the RestApiClient Class
    def __init__(self, config_section='DEFAULT', version=None, config=None):

        if config is None:
            self.config = Config(config_section=config_section)
        else:
            self.config = config

        self.headers = {'Accept': 'application/json'}
        if version is not None:
            self.headers['Version'] = version
        if self.config.has_config_value('auth_token'):
            self.headers['SEC'] = self.config.get_config_value('auth_token')
        elif (self.config.has_config_value('username') and
              self.config.has_config_value('password')):
            username = self.config.get_config_value('username')
            password = self.config.get_config_value('password')
            self.headers['Authorization'] = b"Basic " + base64.b64encode(
                (username + ':' + password).encode('ascii'))
        else:
            raise Exception('No valid credentials found in configuration.')

        self.server_ip = self.config.get_config_value('server_ip')
        self.base_uri = '/api/'

        # Create a secure SSLContext
        # PROTOCOL_SSLv23 is misleading.  PROTOCOL_SSLv23 will use the highest
        # version of SSL or TLS that both the client and server supports.
        context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)

        # SSL version 2 and SSL version 3 are insecure. The insecure versions
        # are disabled.
        try:
            context.options = ssl.OP_NO_SSLv2 | ssl.OP_NO_SSLv3
        except ValueError as e:
            # Disabling SSLv2 and SSLv3 is not supported on versions of OpenSSL
            # prior to 0.9.8m.
            if not (self.config.has_config_value('ssl_2_3_ok') and
                    self.config.get_config_value('ssl_2_3_ok') == 'true'):
                print('WARNING: Unable to disable SSLv2 and SSLv3. Caused '
                      'by exception "' + str(e) + '"')
                while True:
                    response = input(
                        "Would you like to continue anyway (yes/no)? "
                        ).strip().lower()
                    if response == "no":
                        sys.exit(1)
                    elif response == "yes":
                        self.config.set_config_value('ssl_2_3_ok', 'true')
                        break
                    else:
                        print(response + " is not a valid response.")

        context.verify_mode = ssl.CERT_REQUIRED
        if sys.version_info >= (3, 4):
            context.check_hostname = True

        check_hostname = True
        certificate_file = self.config.get_config_value('certificate_file')
        if certificate_file is not None:
            # Load the certificate if the user has specified a certificate
            # file in config.ini.

            # The default QRadar certificate does not have a valid hostname,
            # so me must disable hostname checking.
            if sys.version_info >= (3, 4):
                context.check_hostname = False
            check_hostname = False

            # Instead of loading the default certificates load only the
            # certificates specified by the user.
            context.load_verify_locations(cafile=certificate_file)
        else:
            if sys.version_info >= (3, 4):
                # Python 3.4 and above has the improved load_default_certs()
                # function.
                context.load_default_certs(ssl.Purpose.CLIENT_AUTH)
            else:
                # Versions of Python before 3.4 do not have the
                # load_default_certs method.  set_default_verify_paths will
                # work on some, but not all systems.  It fails silently.  If
                # this call fails the certificate will fail to validate.
                context.set_default_verify_paths()

        install_opener(build_opener(
            HTTPSHandler(context=context, check_hostname=check_hostname)))

    # This method is used to set up an HTTP request and send it to the server
    def call_api(self, endpoint, method, headers=None, params=[], data=None,
                 print_request=False):

        path = self.parse_path(endpoint, params)

        # If the caller specified customer headers merge them with the default
        # headers.
        actual_headers = self.headers.copy()
        if headers is not None:
            for header_key in headers:
                actual_headers[header_key] = headers[header_key]

        # Send the request and receive the response
        request = Request(
            'https://' + self.server_ip + self.base_uri + path,
            headers=actual_headers)
        request.get_method = lambda: method

        # Print the request if print_request is True.
        if print_request:
            SampleUtilities.pretty_print_request(self, path, method,
                                                 headers=actual_headers)

        try:
            response = urlopen(request, data)

            response_info = response.info()
            if 'Deprecated' in response_info:

                # This version of the API is Deprecated. Print a warning to
                # stderr.
                print("WARNING: " + response_info['Deprecated'],
                      file=sys.stderr)

            # returns response object for opening url.
            return response
        except HTTPError as e:
            # an object which contains information similar to a request object
            return e
        except URLError as e:
            if (isinstance(e.reason, ssl.SSLError) and
                    e.reason.reason == "CERTIFICATE_VERIFY_FAILED"):
                print("Certificate verification failed.")
                sys.exit(3)
            else:
                raise e

    # This method constructs the query string
    def parse_path(self, endpoint, params):

        path = endpoint + '?'

        if isinstance(params, list):

            for kv in params:
                if kv[1]:
                    path += kv[0]+'='+quote(kv[1])+'&'

        else:
            for k, v in params.items():
                if params[k]:
                    path += k+'='+quote(v)+'&'

        # removes last '&' or hanging '?' if no params.
        return path[:len(path)-1]

    # Simple getters that can be used to inspect the state of this client.
    def get_headers(self):
        return self.headers.copy()

    def get_server_ip(self):
        return self.server_ip

    def get_base_uri(self):
        return self.base_uri

config.py

class Config:
    """
    Prompt the user for configuration settings. The user has the option to save
    the settings into a configuration file, but this is not required.
    """

    def __init__(self, config_file='config.ini', config_section='DEFAULT'):
        """
        Generate a new Config object. If config_file already exists and
        server_ip is defined in the INI configuration section config_section
        then the settings are read from the config_file. Otherwise the user is
        prompted for the settings and given the option to save the settings to
        config_file. config_file is read from and written to the root of the
        samples directory.
        """

        # Read config_file from the root of the samples directory.
        config_file = os.path.abspath(os.path.dirname(__file__) +
                                      '/../' + config_file)

        self.config_file = config_file
        self.config_section = config_section

        self.config = configparser.ConfigParser()

        create_new_config = True
        if os.path.isfile(config_file):

            self.config.read(config_file)
            if 'server_ip' in self.config[config_section]:
                create_new_config = False

        if create_new_config:

            self._create_new_config()

    def has_config_value(self, config_name):
        """
        Return true if a value for config_name exists in the configuration.
        """

        return config_name in self.config[self.config_section]

    def get_config_value(self, config_name):
        """
        Return the value for config_name, or None if no value for config_name
        exists in the configuration.
        """

        if config_name in self.config[self.config_section]:
            return self.config[self.config_section][config_name]
        else:
            return None

    def set_config_value(self, config_name, config_value):
        """
        Set the value of config_name to config_value.
        """

        self.config[self.config_section][config_name] = config_value

    def write_config_file(self):
        """
        Prompt the user asking if they would like to save the settings,
        including credentials, unencrypted. If they respond yes then save the
        settings to the config file. The Config instance will still work even
        if the settings are not saved to a file.
        """

        choice = _choice("ATTENTION:  It is recommended that you do not " +
                         "leave secure credentials saved unencrypted.\n" +
                         "Store authorization token or password " +
                         "unencrypted: (yes/no)? ",
                         valid_values=("yes", "no"))
        if choice == "yes":
            with open(self.config_file, 'w') as config_file_handle:
                self.config.write(config_file_handle)

    def _create_new_config(self):
        """
        Prompt the user for configuration values. Test if the configuration is
        valid by calling the /help/versions endpoint. If the configuration is
        valid call write_config_value(). If the configuration is not valid
        sys.exit(2) is called.
        """

        config_dict = {}

        config_dict['server_ip'] = input("Please input the IP address or " +
                                         "the hostname of the server you " +
                                         "want to connect to: ").strip()

        choice = _choice("Choose one of the following options for " +
                         "authentication: \n" +
                         "\t1. Authorization token (recommended).\n" +
                         "\t2. Username and password.\n" +
                         "Choice: ", valid_values=("1", "2"))

        if choice == "1":
            config_dict['auth_token'] = input(
                "Please input authorization token: ").strip()
        else:
            config_dict['username'] = input("Username: ").strip()
            config_dict['password'] = getpass.getpass("Password: ")

        certificate_file = _choice("Enter path to TLS PEM certificate " +
                                   "(optional): ", optional=True,
                                   file_exists=True)
        if certificate_file is not None:
            config_dict['certificate_file'] = certificate_file

        self.config[self.config_section] = config_dict

        self._verify_config()

        self.write_config_file()

    def _verify_config(self):
        """
        Verify the configuration is valid by calling the /help/versions
        endpoint. If the request fails print a message indicating the cause of
        the failure and then call sys.exit(2).
        """

        fail_message = None
        try:
            api_client = RestApiClient.RestApiClient(config=self)

            # Only request the /help categories to limit the size of the
            # response.
            params = {'categories': "['/help']"}
            response = api_client.call_api('/help/versions', 'GET',
                                           params=params)
            response.read()
            if response.code == 401 or response.code == 403:
                fail_message = "Authorization failed."
            elif response.code < 200 or response.code > 299:
                response_json = json.loads(response.read().decode('utf-8'))
                fail_message = response_json['http_response']['message']
                fail_message += "\n" + response_json['message']
        except Exception as e:
            fail_message = str(e)

        if fail_message is not None:
            print("Configuration validation failed.")
            print(fail_message)
            print("Check your settings.")
            sys.exit(2)


def _choice(prompt, valid_values=None, file_exists=False, optional=False):
    """
    A method used to help prompt the user for input and validate user input. If
    valid_values is provided _choice confirms the input is in valid_values and
    returns the input. If file_exists is True _choice confirms the file exists
    and returns the absolute path of the file. If optional is True then None
    will be returned if the user does not provide any input.
    """

    choice = input(prompt).strip()
    if optional and choice == "":
        return None

    if valid_values is not None:
        while choice not in valid_values:
            print(choice + " is not a valid option.")
            choice = input(prompt).strip()
            if optional and choice == "":
                return None
    elif file_exists:
        while not os.path.isfile(choice):
            print("File " + choice + " does not exist.")
            choice = input(prompt).strip()
            if optional and choice == "":
                return None
        return os.path.abspath(choice)

    return choice

SampleUtilities.py

import sys
import json


# This function prints out the response from an endpoint in a consistent way.
def pretty_print_response(response):
    print(response.code)
    parsed_response = json.loads(response.read().decode('utf-8'))
    print(json.dumps(parsed_response, indent=4))
    return


# this function prints out information about a request that will be made
# to the API.
def pretty_print_request(client, path, method, headers=None):
    ip = client.get_server_ip()
    base_uri = client.get_base_uri()

    header_copy = client.get_headers().copy()
    if headers is not None:
        header_copy.update(headers)

    url = 'https://' + ip + base_uri + path
    print('Sending a ' + method + ' request to:')
    print(url)
    print('with these headers:')
    print(header_copy)
    print()


# this function sets up data to be used by a sample. If the data already exists
# it prefers to use the existing data.
def data_setup(client, path, method, params=[]):
    response = client.call_api(path, method, params=params)
    if (response.code == 409):
        print("Data already exists, using existing data")
    elif(response.code >= 400):
        print("An error occurred setting up sample data:")
        pretty_print_response(response)
        sys.exit(1)
    return response

urls.py

from django.contrib import admin
from django.urls import path, include
from django.views.generic.base import TemplateView
from django.conf import settings
from django.conf.urls.static import static
from . import views
from . import getoffenses
from project1.getoffenses import getalloffense


urlpatterns = [
    path('admin/', admin.site.urls),

    path('', getalloffense, name='home'),
]

home.html

<p>results</p>

<ul>
{% for j in response_body %}
    <li>{{ j.id }}</li>
{% endfor %}
</ul>

错误

Exception in thread django-main-thread:
Traceback (most recent call last):
  File "c:\users\kiran.tanweer\appdata\local\programs\python\python37-32\Lib\threading.py", line 917, in _bootstrap_inner
    self.run()
  File "c:\users\kiran.tanweer\appdata\local\programs\python\python37-32\Lib\threading.py", line 865, in run
    self._target(*self._args, **self._kwargs)
  File "C:\Users\kiran.tanweer\Envs\celery\lib\site-packages\django\utils\autoreload.py", line 54, in wrapper
    fn(*args, **kwargs)
  File "C:\Users\kiran.tanweer\Envs\celery\lib\site-packages\django\core\management\commands\runserver.py", line 117, in inner_run
    self.check(display_num_errors=True)
  File "C:\Users\kiran.tanweer\Envs\celery\lib\site-packages\django\core\management\base.py", line 390, in check
    include_deployment_checks=include_deployment_checks,
  File "C:\Users\kiran.tanweer\Envs\celery\lib\site-packages\django\core\management\base.py", line 377, in _run_checks
    return checks.run_checks(**kwargs)
  File "C:\Users\kiran.tanweer\Envs\celery\lib\site-packages\django\core\checks\registry.py", line 72, in run_checks
    new_errors = check(app_configs=app_configs)
  File "C:\Users\kiran.tanweer\Envs\celery\lib\site-packages\django\core\checks\urls.py", line 13, in check_url_config
    return check_resolver(resolver)
  File "C:\Users\kiran.tanweer\Envs\celery\lib\site-packages\django\core\checks\urls.py", line 23, in check_resolver
    return check_method()
  File "C:\Users\kiran.tanweer\Envs\celery\lib\site-packages\django\urls\resolvers.py", line 398, in check
    for pattern in self.url_patterns:
  File "C:\Users\kiran.tanweer\Envs\celery\lib\site-packages\django\utils\functional.py", line 80, in __get__
    res = instance.__dict__[self.name] = self.func(instance)
  File "C:\Users\kiran.tanweer\Envs\celery\lib\site-packages\django\urls\resolvers.py", line 579, in url_patterns
    patterns = getattr(self.urlconf_module, "urlpatterns", self.urlconf_module)
  File "C:\Users\kiran.tanweer\Envs\celery\lib\site-packages\django\utils\functional.py", line 80, in __get__
    res = instance.__dict__[self.name] = self.func(instance)
  File "C:\Users\kiran.tanweer\Envs\celery\lib\site-packages\django\urls\resolvers.py", line 572, in urlconf_module
    return import_module(self.urlconf_name)
  File "C:\Users\kiran.tanweer\Envs\celery\lib\importlib\__init__.py", line 127, in import_module
    return _bootstrap._gcd_import(name[level:], package, level)
  File "<frozen importlib._bootstrap>", line 1006, in _gcd_import
  File "<frozen importlib._bootstrap>", line 983, in _find_and_load
  File "<frozen importlib._bootstrap>", line 967, in _find_and_load_unlocked
  File "<frozen importlib._bootstrap>", line 677, in _load_unlocked
  File "<frozen importlib._bootstrap_external>", line 728, in exec_module
  File "<frozen importlib._bootstrap>", line 219, in _call_with_frames_removed
  File "C:\celery\project1\project1\urls.py", line 22, in <module>
    from . import getoffenses
  File "C:\celery\project1\project1\getoffenses.py", line 28, in <module>
    client_module = importlib.import_module('./modules/RestApiClient')
  File "C:\Users\kiran.tanweer\Envs\celery\lib\importlib\__init__.py", line 122, in import_module
    raise TypeError(msg.format(name))
TypeError: the 'package' argument is required to perform a relative import for './modules/RestApiClient'

0 个答案:

没有答案