我是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'