如何将过滤的保管箱用于外部数据库值

时间:2019-04-09 07:10:03

标签: python django

我正在学习Django为我的python项目做一个前端,在这里我需要创建一个凭证表单来与数据库工具e.q建立连接。我创建的PostgreSQL。现在,我想要一个下拉列表列出PostgreSQL中可用的所有数据库,然后另一个下拉列表在第一个下拉列表中列出所选数据库中存在的所有模式,然后使用第二个下拉列表列出所选模式中存在的表的另一个下拉菜单。

我为此检查了许多视频,但所有视频都与模型一起显示。但是我希望这些下拉值来自外部数据库而不是来自模型。

我试图创建一个python文件,以便在Django应用程序内部创建一个表单,其中我正在使用Forms.ChoiceField列出数据库值。但无法获得下拉菜单的选定值。这样我就可以查询架构了

2 个答案:

答案 0 :(得分:0)

您可以这样做:

  1. 返回所有数据库
import psycopg2


conn = psycopg2.connect(
    database="test",
    user="root",
    password="root",
    host="127.0.0.1",
    port="5432"
)

cursor = conn.cursor()

# first: get all databases
cursor.execute(
    """
    SELECT datname
    FROM pg_database
    WHERE datistemplate = false;
    """
)
rows = cursor.fetchall()
dbs = [row[0] for row in rows]

cursor.close()
conn.close()

前端呈现下拉菜单,然后使用所选数据库查询所有架构。

  1. 返回所有架构
import psycopg2


conn = psycopg2.connect(
    database="test",
    user="root",
    password="root",
    host="127.0.0.1",
    port="5432"
)

cursor = conn.cursor()
# second: get all schemas
# DB is the database selected in the previous step
cursor.execute(
    """
    SELECT schema_name
    FROM information_schema.schemata
    WHERE catalog_name = 'DB';
    """
)
rows = cursor.fetchall()

schemes = [row[0] for row in rows]
cursor.close()
conn.close()

与上一个相同,然后使用选定的架构和数据库查询所有表

  1. 返回所有表格
import psycopg2


conn = psycopg2.connect(
    database="test",
    user="root",
    password="root",
    host="127.0.0.1",
    port="5432"
)

cursor = conn.cursor()
# third: get all tables
# SCHEMA is the schema selected in the previous step
cursor.execute(
    """
    SELECT table_name
    FROM information_schema.tables
    WHERE table_schema = 'SCHEMA'
        AND table_catalog = 'DB';
    """
)
rows = cursor.fetchall()

tables = [row[0] for row in rows]

cursor.close()
conn.close()

您可以将以上代码嵌入到django代码中,以进行下一步操作。

答案 1 :(得分:0)

例如,我创建了一个项目t_project和一个应用程序t_app
我已经使用psycopg2库来使用原始光标(没有Django包装器)浏览数据库。
我已经手动设置了field.choices和从psycopg获得的值。


# /t_project/settings.py

INSTALLED_APPS = [
    # ...
    't_app.apps.TAppConfig',
]

# /t_project/urls.py

from django.urls import path

from t_app import views as t_app_views

urlpatterns = [
    path('', t_app_views.TestView.as_view(), name='test'),
    path('<str:database>/', t_app_views.TestView.as_view(), name='test'),
    path('<str:database>/<str:schema>/', t_app_views.TestView.as_view(), name='test'),
]

# /t_app/templates/t_app/test.html

<form method="post">
    {% csrf_token %}
    {{ form.as_p }}
    <input type="submit" value="Submit"/>
</form>

# /t_app/views.py

import psycopg2
from django import forms
from django.http import HttpResponseRedirect
from django.urls import reverse
from django.views import generic


class DBForm(forms.Form):
    database = forms.ChoiceField()

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)

        self.fields['database'].choices = self._get_databases()

    def _get_databases(self):
        conn_string = "host='localhost' dbname='postgres' user='postgres' password='postgres_pass'"
        with psycopg2.connect(conn_string) as conn:
            cursor = conn.cursor()

            cursor.execute('SELECT datname FROM pg_database WHERE datistemplate = FALSE')
            return [(d, d) for d, in cursor.fetchall()]


class SchemaForm(DBForm):
    schema = forms.ChoiceField()

    def __init__(self, database, *args, **kwargs):
        super().__init__(*args, **kwargs)

        self.fields['database'].initial = database
        self.fields['schema'].choices = self._get_schemas(database)

    def _get_schemas(self, database):
        # TODO Do NOT forget to escape "database" here to prevent injections
        conn_string = f"host='localhost' dbname='{database}' user='postgres' password='postgres_pass'"
        with psycopg2.connect(conn_string) as conn:
            cursor = conn.cursor()

            cursor.execute('SELECT schema_name FROM information_schema.schemata')
            return [(s, s) for s, in cursor.fetchall()]


class TableForm(SchemaForm):
    table = forms.ChoiceField()

    def __init__(self, database, schema, *args, **kwargs):
        super().__init__(database, *args, **kwargs)

        self.fields['schema'].initial = schema
        self.fields['table'].choices = self._get_tables(database, schema)

    def _get_tables(self, database, schema):
        # TODO Do NOT forget to escape "database" here to prevent injections
        conn_string = f"host='localhost' dbname='{database}' user='postgres' password='postgres_pass'"
        with psycopg2.connect(conn_string) as conn:
            cursor = conn.cursor()

            cursor.execute('SELECT tablename FROM pg_catalog.pg_tables WHERE schemaname = %s', (schema,))
            return [(t, t) for t, in cursor.fetchall()]


class TestView(generic.FormView):
    template_name = 't_app/test.html'

    def get_form(self, form_class=None):
        kwargs = self.get_form_kwargs()

        database = self.kwargs.get('database')
        schema = self.kwargs.get('schema')
        if schema:
            return TableForm(database=database, schema=schema, **kwargs)
        if database:
            return SchemaForm(database=database, **kwargs)
        return DBForm(**kwargs)

    def form_valid(self, form):
        database = form.cleaned_data.get('database')
        schema = form.cleaned_data.get('schema')
        table = form.cleaned_data.get('table')
        if table:
            print('Exit is here')
        if schema:
            return HttpResponseRedirect(reverse('test', kwargs={'schema': schema, 'database': database}))
        if database:
            return HttpResponseRedirect(reverse('test', kwargs={'database': database}))
        return HttpResponseRedirect(reverse('test'))