Zwei Funktionen der selben URL übergeben

Django, Flask, Bottle, WSGI, CGI…
Antworten
Benutzeravatar
Prinz_Monty
User
Beiträge: 18
Registriert: Mittwoch 24. Oktober 2018, 09:43

Wie kann ich in Django zwei oder mehr Funktionen einer URL übergeben? Oder ist das so nicht vorgesehen?

Views.py:

Code: Alles auswählen

def one(request):
    one = two
    return render(request, 'enemene/enemene.html', {'one': one})

def two(request):
    two = one
    return render(request, 'enemene/enemene.html', {'two': two})
    

urls.py:

Wie müsste ich das hier darstellen um zum beispiel Funktion two auch auf der Seite "enemene" zu übergeben?

Code: Alles auswählen

urlpatterns = [
    path('', views.index, name='index'),
    path('enemene/', views.one, name='dingdong'),
]
Zuletzt geändert von Prinz_Monty am Mittwoch 7. November 2018, 23:39, insgesamt 2-mal geändert.
Mögen hätt ich schon wollen, aber dürfen habe ich mich nicht getraut. *Karl Valentin
Sirius3
User
Beiträge: 17711
Registriert: Sonntag 21. Oktober 2012, 17:20

Was willst Du eigentlich erreichen? Aus der Erklärung werde ich nicht recht schlau.
Benutzeravatar
Prinz_Monty
User
Beiträge: 18
Registriert: Mittwoch 24. Oktober 2018, 09:43

Ich möchte die Funktion one() und two() der Seite enemene/ übergeben. Wie gesagt vielleicht ist das so nicht vorgesehen aber habe in der Doku dazu nichts gefunden.
Mögen hätt ich schon wollen, aber dürfen habe ich mich nicht getraut. *Karl Valentin
__deets__
User
Beiträge: 14494
Registriert: Mittwoch 14. Oktober 2015, 14:29

Du kannst keine zwei Funktionen an eine URL binden. Was soll denn dabei auch rauskommen? Zwei antworten, und dein Browser macht nen Split Screen? Du kannst dir eine Funktion three schreiben, die one oder two oder beide aufruft. Ein Ergebnis kann aber immer nur ein einziges abgeliefert werden.
Sirius3
User
Beiträge: 17711
Registriert: Sonntag 21. Oktober 2012, 17:20

Man kann keine Funktionen einer Seite übergeben, eine Funktion erzeugt den Inhalt einer Seite und wenn man zwei Funktionen hat, braucht man eine dritte, die den Teilinhalt der zwei Funktionen zu einer Seite zusammensetzt.
Benutzeravatar
Prinz_Monty
User
Beiträge: 18
Registriert: Mittwoch 24. Oktober 2018, 09:43

In der Urls.py in meiner App werden doch aber die Urls zusammengebaut und was auf welcher ankommen soll.



path('enemene/', views.one, name='dingdong'), <- views.one Ist die Funktion aus der views.py die über die seite simsalabim.de/enemene/ erreichbar ist. Wenn ich jetzt aber auch eine Funktion habe die auch auf der seite /enemene/ abrufbar sein soll dann muss ich das doch auch irgendwie dem system sagen. Muss ich da echt eine Extra Funktion bauen?

Das hier funktioniert halt nicht:

Code: Alles auswählen

urlpatterns = [
    path('', views.index, name='index'),
    path('enemene/', views.one, name='dingdong'),
    path('enemene/', views.two, name='blub'),
]
Mögen hätt ich schon wollen, aber dürfen habe ich mich nicht getraut. *Karl Valentin
Benutzeravatar
__blackjack__
User
Beiträge: 13004
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@Prinz_Monty: Wie genau stellst Du Dir denn vor wie das System damit umgehen soll das eine URL auf zwei Funktionen *gleichzeitig* abgebildet wird? Jede Funktion liefert ja *das* Ergebnis, also zum Beispiel eine komplette HTML-Seite. Was soll denn dann der Browser mit zwei kompletten HTML-Seiten gleichzeitig machen?

Wenn das denn ginge, denn das sieht HTTP so nicht vor. Da gibt es eine Anfrage und eine Antwort darauf. Und wenn das ein HTML-Dokument ist, dann zeigt der Browser das an.
“Most people find the concept of programming obvious, but the doing impossible.” — Alan J. Perlis
Benutzeravatar
Prinz_Monty
User
Beiträge: 18
Registriert: Mittwoch 24. Oktober 2018, 09:43

Okay. Also ist es so das eine Funktion den View regelt und quasi andere Funktionen bündelt für die Ausgabe? Dann würde es ja auch wieder sinn machen dies in eine Klasse zupacken?

Ich finde es lustig komme mir etwas verfolgt vor das mir meistens die gleichen leute hier eine Antwort liefern. Danke das ich noch nicht aufgegeben wurde : -)
Mögen hätt ich schon wollen, aber dürfen habe ich mich nicht getraut. *Karl Valentin
__deets__
User
Beiträge: 14494
Registriert: Mittwoch 14. Oktober 2015, 14:29

Ob das Sinn macht das in eine Klasse zu packen haengt davon ab, was die machen. Erstmal macht es das nicht, denn dein view nimmt nur ein callable - also eine Funktion. Das koennte zwar auch eine bound method einer existierenden Klasse sein, aber damit hast du davon eh nur eine Instanz. Das ist dann genauso gut wie eine freistehende Funktion. Sogar schlechter, weil du sonst self._irgendwas quasi als globalen Zustand benutzt und dir jede Menge Bugs reinholst. Ob sich *in* deiner View-Funktion dann die Instantiierung einer Klasse anbietet - kA.

So wie du das formulierst scheinst du zu denken, Klassen sind nur Sammlungen von Funktionen. Sind sie nicht. Sie sind *ZUSTAND* mit dazugehoerigen Funktionen. Ohne eine sinnvolle Idee, was und wo dieser Zustand eine Rolle spielt, bringen sie nichts.
Benutzeravatar
kbr
User
Beiträge: 1487
Registriert: Mittwoch 15. Oktober 2008, 09:27

Eine View lässt sich durchaus als Klasse umsetzen. Das kann sogar sinnvoll sein, ist aber nichts für den Einstieg.

Und selbstverständlich lassen sich auch verschiedene Views an die gleiche url binden. Das hat nur keinen Effekt (wie du bereits festgestellt hast), da bei der Auswertung der erste Treffer gewinnt, also stets die gleiche View aufgerufen wird. Glücklicherweise, denn sonst hätte das Programm ein willkürliches Verhalten.

Also: eine url, eine View. Genau dafür dienen die Abbildungen in Django. Wie komplex dann die View (auch als Funktion) ausfällt, ist eine andere Frage. Natürlich kannst du von dort auch andere Funktionen aufrufen. Die View ist ja nur der Einstiegspunkt für die gegebene url.
Benutzeravatar
Prinz_Monty
User
Beiträge: 18
Registriert: Mittwoch 24. Oktober 2018, 09:43

kbr hat geschrieben: Donnerstag 8. November 2018, 12:51 Eine View lässt sich durchaus als Klasse umsetzen. Das kann sogar sinnvoll sein, ist aber nichts für den Einstieg.

Und selbstverständlich lassen sich auch verschiedene Views an die gleiche url binden. Das hat nur keinen Effekt (wie du bereits festgestellt hast), da bei der Auswertung der erste Treffer gewinnt, also stets die gleiche View aufgerufen wird. Glücklicherweise, denn sonst hätte das Programm ein willkürliches Verhalten.

Also: eine url, eine View. Genau dafür dienen die Abbildungen in Django. Wie komplex dann die View (auch als Funktion) ausfällt, ist eine andere Frage. Natürlich kannst du von dort auch andere Funktionen aufrufen. Die View ist ja nur der Einstiegspunkt für die gegebene url.
Genau nur der erste Treffer liefert dann ein Ergebnis.

Wie du merkst, ich stehe noch ganz am Anfang und hab mir einfach ein Projekt ausgedacht an dem ich üben kann ohne Zeitdruck aber mit vollen Umfang. Und wenn ich es mal fertig habe so in einem Jahr * lach dann freu ich mich und beim nächsten kann ich es dann hoffentlich besser.

Zum Verständnis:

Also muss ich wenn ich verschiedene Dinge auf einer URL ausgeben möchte, diese alle gebündelt in eine Funktion schreiben.Oder verschiedene Funktionen gebündelt über eine extra Funktion die sich um den view kümmert schicken. Richtig?
Mögen hätt ich schon wollen, aber dürfen habe ich mich nicht getraut. *Karl Valentin
Benutzeravatar
kbr
User
Beiträge: 1487
Registriert: Mittwoch 15. Oktober 2008, 09:27

Verschiedene Dinge über eine URL ist der falsche Ansatz.
Verschiedene Dinge -> verschiedene URLs -> verschiedene Views.
Benutzeravatar
Prinz_Monty
User
Beiträge: 18
Registriert: Mittwoch 24. Oktober 2018, 09:43

kbr hat geschrieben: Donnerstag 8. November 2018, 13:26 Verschiedene Dinge über eine URL ist der falsche Ansatz.
Verschiedene Dinge -> verschiedene URLs -> verschiedene Views.
Ich bin wohl etwas schwer von begriff oder muss es besser erklären.

Ein beispiel.

Ich habe eine URL/Seite simsalabim.de/domains/. Auf dieser Seite werden alle Domains aufgelistet die ich besitze. Diese kommen aus einer Funktion die eine API Callt (wenn man das da so sagt). Jetzt möchte ich aber noch weitere Daten zu den jeweiligen Domains ausgeben zb. den Inhaber dieser kommt aus einer anderen Funktion. Wie übergebe ich den Inhaber dann der Seite simsalabim.de/domains/ ?

Meine urls.py sieht gerade so aus:

Code: Alles auswählen

urlpatterns = [
    path('', views.index, name='index'),
    path('domains/', views.domains_by_status, name='domains'),
]
Mögen hätt ich schon wollen, aber dürfen habe ich mich nicht getraut. *Karl Valentin
Sirius3
User
Beiträge: 17711
Registriert: Sonntag 21. Oktober 2012, 17:20

Du mischt zwei Dinge, die getrennt sein sollten:
1. Erzeugen von Daten (Abfragen, Zusammenstellen, etc)
2. Anzeigen der Daten

Das Sammeln und Aufbereiten der Daten kann natürlich in mehreren Funktionen stattfinden, aber zum Schluß ist das ein Aufruf, der die Daten in der Form liefert, wie Du sie dann auch darstellen willst.

Das Anzeigen ist bei Django dann einfach zum Schluß der `render`-Aufruf.
Benutzeravatar
Prinz_Monty
User
Beiträge: 18
Registriert: Mittwoch 24. Oktober 2018, 09:43

Sirius3 hat geschrieben: Donnerstag 8. November 2018, 14:21 Du mischt zwei Dinge, die getrennt sein sollten:
1. Erzeugen von Daten (Abfragen, Zusammenstellen, etc)
2. Anzeigen der Daten

Das Sammeln und Aufbereiten der Daten kann natürlich in mehreren Funktionen stattfinden, aber zum Schluß ist das ein Aufruf, der die Daten in der Form liefert, wie Du sie dann auch darstellen willst.

Das Anzeigen ist bei Django dann einfach zum Schluß der `render`-Aufruf.
Ja ok das ist schon irgendwie klar. Aber wie bitte übergebe ich dann in der urls.py Funktion A, B, C, D der URL /domains? Das verstehe ich nicht. Ich kann dort nur einmal pro URL eine Funktion angeben. Also so wie ich es jetzt mache path('domains/', views.domains_by_status, name='domains'), .....
Mögen hätt ich schon wollen, aber dürfen habe ich mich nicht getraut. *Karl Valentin
Benutzeravatar
__blackjack__
User
Beiträge: 13004
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@Prinz_Monty: Du übergibst gar keine Funktionen an URLs, Du hast eine Abbildung von URLs auf Funktionen, mit einer Funktion pro URL. Und in dieser einen Funktion musst Du dann alles machen was am Ende nötig ist um die Antwort für den Aufruf der URL zusammenzustellen. Wobei in der Funktion etwas machen auch das aufrufen von anderen Funktionen beinhalten kann, die dann Teilaufgaben lösen. Das heisst in dieser einen Funktion kannst Du die Funktionen A, B, C, und D aufrufen und aus deren Rückgabewerten Dein Ergebnis für die URL zusammensetzen. Also ganz normal wie man auch ohne Django programmieren würde. Durch Django ändert sich an dieser üblichen Vorgehensweise nichts.
“Most people find the concept of programming obvious, but the doing impossible.” — Alan J. Perlis
sagro
User
Beiträge: 6
Registriert: Freitag 19. Oktober 2018, 20:50

Hallo,

es würde die Sache vereinfachen, wenn du dein Problem konkretisieren würdest. Also, was machen diese zwei Views konkret, dass Sie auf eine URL aufgelöst werden sollen? Ist es eine App für Kochrezepte? Ich denke, wenn du das ein wenig genauer ausführst, kann man eventuell das Problem anderweitig lösen ;O)

Grüße
sagro
Benutzeravatar
Prinz_Monty
User
Beiträge: 18
Registriert: Mittwoch 24. Oktober 2018, 09:43

sagro hat geschrieben: Donnerstag 8. November 2018, 19:03 Hallo,

es würde die Sache vereinfachen, wenn du dein Problem konkretisieren würdest. Also, was machen diese zwei Views konkret, dass Sie auf eine URL aufgelöst werden sollen? Ist es eine App für Kochrezepte? Ich denke, wenn du das ein wenig genauer ausführst, kann man eventuell das Problem anderweitig lösen ;O)

Grüße
sagro
Also ich habe eine Funktion die bekommt Daten von einer API aus einer Domain Verwaltung ( ISPConfig ). Das funktioniert nun auch ganz toll, auch dank dieses Forums hier.
Ich möchte eine App bauen welche mir ermöglicht mit den Daten von der API eine Übersicht der Domains und deren Abrechnungszeiträume darzustellen.

Also ich möchte:

1. Alle Aktiven und Deaktivierten Domains anzeigen
2. Alle Domains zu einem bestimmten Kunden
3. Sortierung nach Rechnungsdatum (Alle 12 Monate) oder nach Kunden
4. Detailansicht zu jeder Domain mit einem Formular welches mir ermöglicht Notizen zu jeder Domain anzulegen (Das Notiz Feld ist ein teil von ISPConfig also benötige ich dafür keine Datenbank)
5. Möchte ich einen Status setzen können Domain Abgerechnet am: , Domain bezahlt am: , Mahnung 1 am: , Mahnung 2 am: , Das ganze soll in der Übersicht aller Domains farbig Dargestellt werden was ich vermutlich über Bootstrap machen werde.
6. Später vielleicht noch einen Userlogin. Dazu gibts ja aber auch genug Anleitungen.

Jetzt mein IST Zustand:

Ich habe eine Klasse die mit der API kommuniziert:

Code: Alles auswählen

import requests
import logging
logger = logging.getLogger("ispconfig")

BASE_URL = 'https://127.0.0.1/remote/json.php'


class ISPConfig:
    def __init__(self, base_url):
        self.base_url = base_url
        self.session_id = None

    # Session ID capsle
    def _call(self, command, **params):
        if self.session_id:
            params['session_id'] = self.session_id
        response = requests.post(self.base_url, params=command, json=params).json()
        if response['code'] != 'ok':
            raise RuntimeError(f'Fehler bei {command}: {response["message"]}')
        return response['response']

    # Login send
    def login(self, username, password):
        self.session_id = None
        self.session_id = self._call('login', username=username, password=password)
        logger.info('Erfolgreich angemeldet: %s', self.session_id)

    # Get a domain by id
    def sites_web_domain_get(self, primary_id):
        return self._call('sites_web_domain_get', primary_id=primary_id)

    # Get all active = 'y' or none active domains 'n'
    def sites_web_domain_get_all(self, active):
        return self._call('sites_web_domain_get', primary_id={'active': active})

    # Get client by id (9=Merker)
    def client_get(self, client_id):
        return self._call('client_get', client_id=client_id)

    # Get all API functions '1'
    def get_function_list(self, function_list):
        return self._call('get_function_list', primary_id=function_list)

    def domains_get_all_by_user(self, group_id):
        return self._call('domains_get_all_by_user', group_id=group_id)

    # Add notice to clients
    def client_update(self, client_id, affected_row):
        return self._call('client_update', client_id=client_id, params={'notes': affected_row})

    # Get all domains by single user with groupid
    def client_get_sites_by_user(self, sys_groupid):
        return self._call('client_get_sites_by_user', sys_groupid=sys_groupid)
        
Zwei Funktionen eine für die Connection zur API und eine die mir bis jetzt alle Domains liefert nach Status Aktiviert oder Deaktiviert oder alle Domains von einem User über die die UserId (sys_groupid):

Code: Alles auswählen

from django.shortcuts import render
from domain_cm.ispconfig import ISPConfig


def index(request):
    return render(request, 'domain_cm/index.html')


def connection_api():
    base_url = 'https://127.0.0.1/remote/json.php'
    isp_config = ISPConfig(base_url)
    isp_config.login("USER", "PASSWORD")

    return isp_config


def domains_by_status(request):
    domains_active = connection_api().sites_web_domain_get_all("y")
    domains_disable = connection_api().sites_web_domain_get_all("n")
    domains_by_user = connection_api().client_get_sites_by_user("2")

    return render(request, 'domain_cm/domains.html', {'domains_active': domains_active,
                                                      'domains_disable': domains_disable,
                                                      'domains_by_user': domains_by_user,
                                                      })
urls.py:

Code: Alles auswählen

from django.urls import path
from . import views

app_name = 'domains'
urlpatterns = [
    path('', views.index, name='index'),
    path('domains/', views.domains_by_status, name='domains'),
]
Das ganze gebe ich mir erstmal nur mit paar for schleifen im Template aus:

Code: Alles auswählen

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Domains</title>
</head>
<body>
    <p>Aktiviert:</p>
    {% for domain_active in domains_active %}
        <p>ID: {{ domain_active.domain_id }} Domain: {{ domain_active.name }} Added: {{ domain_active.added_date }}</p>
    {% endfor %}
    <p>Deaktiviert:</p>
    {% for domain_disable in domains_disable %}
        <p>ID: {{ domain_disable.domain_id }} Domain: {{ domain_disable.name }} Added: {{ domain_disable.added_date }}</p>
    {% endfor %}
    <p>Domains von User:</p>
    {% for domain_by_user in domains_by_user %}
        <p>{{ domain_by_user }}</p>
    {% endfor %}

</body>
</html>
Hier stehe ich gerade vor einer neuen Aufgabe wie ich per POST zb. den Status == "y" übergebe? Will das ja nicht von der Funktion aus machen sondern zb. Per Dropdown Menü auswählen können. Also muss ich ja den Status per form Formular an den Code übergeben.

Zu meiner eigentlichen frage wie ich verschiedene Dinge auf einer Seite anzeige ist mir nun langsam klarer das ich dies in einer Funktion oder Klasse lösen sollte. Einiges lässt sich ja auch schon durch die Template Engine realisieren also muss ich ja nicht alles in einer Funktion darstellen. Zb. Sortierungen etc.

So das ist nun alles was ich habe und wo ich am Ende hin möchte.
Mögen hätt ich schon wollen, aber dürfen habe ich mich nicht getraut. *Karl Valentin
Sirius3
User
Beiträge: 17711
Registriert: Sonntag 21. Oktober 2012, 17:20

connection_api sollte man maximal einmal pro Request aufrufen, Du rufst ja jetzt grad ständig überflüssigerweise login auf. url, user und password sollte in einer Konfigurationsdatei stehen, z.B. settings.py wo schon viel anderes Zeug steht.
Antworten