Как я могу использовать отфильтрованный Dropbox для значений моей внешней базы данных

Я изучаю Django, чтобы создать интерфейс для моего проекта Python, где мне нужно создать форму учетных данных, чтобы установить соединение с инструментом базы данных, например. PostgreSQL, который я создал. Теперь я хочу, чтобы раскрывающийся список отображал все базы данных, доступные в моем PostgreSQL, а затем еще один раскрывающийся список, чтобы перечислять все схемы, присутствующие в выбранной базе данных, в первом раскрывающемся списке, а затем еще один раскрывающийся список для таблиц, присутствующих в выбранной схеме, используя второй раскрывающийся список.

Я проверил много видео для этого, но все показывают с моделями. Но мне нужны эти выпадающие значения из внешней базы данных, а не из моделей.

Я попытался создать файл python для создания формы внутри моего приложения Django, где я использую forms.ChoiceField для отображения значений базы данных. Но не удалось получить выбранное значение для раскрывающегося списка. Чтобы я мог запросить схемы

Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
0
0
62
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ты можешь это сделать:

  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, чтобы сделать следующее.

Я уже написал код на Python, чтобы получить все это. Я не могу встроить его в интерфейс django.

JaswantSingh 09.04.2019 12:19
Ответ принят как подходящий

Для примера я создал проект 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'))

Спасибо @mistru за то, что поделились. Работает по схеме. это дает мне ошибку «требуемое поле», когда я выбираю схему. Я попытался распечатать схему внутри класса TestView и показывает мне «Нет».

JaswantSingh 10.04.2019 06:33

@JaswantSingh Хорошо, это было из-за атрибута «отключено» (я добавил в свой пост после тестирования), который не позволяет форме отправлять значение. Я отредактировал свой пост, и теперь он работает;)

mistiru 10.04.2019 20:11

Спасибо, @mistiru за помощь. Сейчас это работает. Но у меня другой вопрос, можем ли мы сделать это без кнопки отправки?

JaswantSingh 11.04.2019 06:37

Да, мы можем сделать все, что вы хотите ^^ Без кнопки отправки вы можете прикрепить к полю прослушиватель «onchange» (с javascript, на всякий случай;)), и этот слушатель отправит форму, или вы можете сделать это с ajax или вообще с чем угодно ^^ Я просто привел минимальный пример (поэтому я использовал наследование)

mistiru 11.04.2019 20:42

Другие вопросы по теме