Seite 1 von 1

Models

Verfasst: Dienstag 10. September 2019, 15:16
von Freumel
Hallo zusammen,

Aktuell beschäftige ich mich ein wenig mit Datenbanken und stelle fest: ich habe einfach zu wenig Ahnung, sowohl von den Möglichkeiten an sich, als auch die Möglichkeiten die Django bietet, also versuche ich es zu lernen. Learning by Doing.

Nun habe ich mir ein paar recht greifbare Dinge ausgedacht und diese auch so umgesetzt, dass sie irgendwie funktionieren.

Eines meiner vielen Probleme ist, dass ich nicht weiß wie ich mit wiederkehrenden Elementen umzugehen habe.

Bei zwei Anliegen komme ich aber nicht weiter:
1. Aufträge geben
Ziel: ein Kunde (Customer) hat einen Auftrag (Order). Dieser Auftrag kann ein einmaliges Event mit Start und Endzeitpunkt an einem bestimmten Tag sein, oder ein geteiltes Event (z.B. Von 12-14 und von 17-20 Uhr) sowie in unregelmäßigen Abständen nach genau diesem Prinzip mehrfach im Monat stattfinden.

Dazu habe ich folgende Tabellen angelegt:

Code: Alles auswählen

class Customer(models.Model):
    first_name = models.CharField(max_length=30, blank=True)
    last_name = models.CharField(max_length=30) 
    email = models.EmailField(primary_key=True)

    def __str__(self):
        return self.email

class Order(models.Model):
    title = models.CharField(max_length=60)
    start = models.DateTimeField()
    end = models.DateTimeField()
    customer = models.ForeignKey(Customer, on_delete=models.CASCADE)

    def __str__(self):
        return '{} // {}'.format(self.title, self.customer.email) 
Das Problem hier: besagte Unterbrechungen sind nur umsetzbar, indem ich für jede Pause einen neuen Eintrag anlege.

2. Statistiken
Es wird eine Datenbank für Ereignisse an verschiedenen Kreuzungen (Location) angelegt. Dabei wirs alle 15 Minuten ein Ereignis (Event) angelegt bezüglich Wetter, Fußgängerzahl an der Ampel, Autos und Unfälle.

Auch hier habe ich Ereignisse angelegt:

Code: Alles auswählen

class Location(models.Model):
    zip_code = models.Integerfield()
    start = models.DateTimeField() 

    def __str__(self):
        return '{} // {}'.format(self.zip, self.start)

class Event(self):
    weather = models.CharField(max_length = 2, choices=WEATHER)
    people_count = models.Integerfield(default=0)
    car_count = models.Integerfield(default=0)
    crash = models.BooleanField(default=False)
    location = models.ForeignKey(Location, on_delete=models.CASCADE)
Das Problem hier: ich habe von der Uni noch einen alten Datensatz (csv) als Vorbereitung auf das Laborpraktikum zum auswerten bekommen. Am liebsten hätte ich die Zuordnung der Ereignisse direkt als ManyToMany Field an der Location. Wenn ich das so mache, hängt sich der ganze Adminbereich beim Erstellen oder Öffnen eines Objektes auf - der Datensatz hat über 1mb.

Gefühlt ist beides recht suboptimal umgesetzt, erfüllt halt nur irgendwie seinen Zweck.

Gibt es eventuell ein paar Tipps oder nette Links speziell der Umsetzung betreffend?

Re: Models

Verfasst: Dienstag 10. September 2019, 15:57
von noisefloor
Hallo,

zu 1: ich würde da eine 3. Tabelle `Event` anlegen, wenn einer One-To-Many Beziehung zur `Order`. Weil jede Order kann ja X Events beinhalten.

zu 2: Wieso Many-to-Many? Jedes Event ist doch genau einer Location zugeordnet?

BTW: wenn du dich mit Datenbanken beschäftigst heißt das nicht, dass du Django nutzen musst. Eher umgekehr: Das Django ORM nimmt man eigentlich "nur", wenn man seine Webanwendung mit Django macht. Klar kann man das ORM auch ohne den Rest nutzen, dass ist aber eher... ungewöhnlich.

Mir persönlich hat es übrigens geholfen, dass ich mich erst mit RDBMS beschäftigt haben, bevor ich ein ORM genutzt habe. IMHO ist es ganz nützlich, wenn man ein bisschen SQL und die Möglichkeiten von RDBMS kennt, bevor man ein ORM nutzt. Dazu muss man nicht ein RDBMS wie PostgreSQL oder MariaDB oder ... bis in epischer Tiefe kenne. Aber IMHO schadet es nicht, wenn man weiß, wie CRUD, einfache Joins oder Aggregation mit SQL funktionieren.

Gruß, noisefloor

Re: Models

Verfasst: Dienstag 10. September 2019, 16:10
von Bolitho
bei 2 geht es um die Pflege im Admin, wenn ich das richtig verstehe. Es soll über das Location-Model die entsprechenden Events ausgewählt werden. Dafür braucht es ein Admin-Inline. Mit Code kann ich gerade leider nicht dienen.

Re: Models

Verfasst: Dienstag 10. September 2019, 16:19
von __blackjack__
Beim 2. gehört der Zeitstempel doch eher an das `Event` und `Location.start` ist dann überflüssig, denn das ist ja der kleinste Zeitstempel zu den `Event`-Datensätzen und kann auf diese Weise auch abgefragt werden. `Event` würde ich hier wohl eher `Observation` nennen.

Bei der Beschränkung der Länge von Namensfeldern wäre ich übrigens deutlich grosszügiger.

Re: Models

Verfasst: Mittwoch 11. September 2019, 01:34
von Freumel
Bolitho hat geschrieben: Dienstag 10. September 2019, 16:10 bei 2 geht es um die Pflege im Admin, wenn ich das richtig verstehe. Es soll über das Location-Model die entsprechenden Events ausgewählt werden. Dafür braucht es ein Admin-Inline. Mit Code kann ich gerade leider nicht dienen.
:idea: :idea: :idea: :idea: :idea:
Danke!

Inline war das Zauberwort.

Re: Models

Verfasst: Mittwoch 11. September 2019, 07:14
von Sirius3
@Freumel: Tabelleneinträge sind ungeordnet. Bei Deiner Event-Tabelle weiß man nicht, wann welches Ereignis aufgetreten ist. Das 15-Minuten-Intervall seit Start muß also explizit gespeichert werden, oder die __blackjack__ schon geschrieben hat, gehört die Zeit zum Event.
Auch wenn Django implizit ID-Felder erzeugt, ist es doch besser, sie explizit zu definieren, weil Du dann auch besser weißt, wie die Datenbank funktioniert.

Zur Frage mit der Order: Du solltest zuerst überlegen, welche Daten nötig sind, damit Du per Papier und Bleistift eine Order komplett beschreiben kannst. Da kannst Du dann entweder n Zeiträume von-bis haben, oder einen Start-End-Termin mit einem zusätzlichen Pause-von-bis. Was die ideale Speicherung ist, hängt auch davon ab, was Du mit den Daten weiter machen willst. Daher ist der erste Schritt, eine Liste mit Fragen aufzuschreiben, die man von der Datenbank beantwortet haben möchte.

Re: Models

Verfasst: Mittwoch 11. September 2019, 18:11
von Freumel
Sirius3 hat geschrieben: Mittwoch 11. September 2019, 07:14 @Freumel: Tabelleneinträge sind ungeordnet. Bei Deiner Event-Tabelle weiß man nicht, wann welches Ereignis aufgetreten ist. Das 15-Minuten-Intervall seit Start muß also explizit gespeichert werden, oder die __blackjack__ schon geschrieben hat, gehört die Zeit zum Event.
Auch wenn Django implizit ID-Felder erzeugt, ist es doch besser, sie explizit zu definieren, weil Du dann auch besser weißt, wie die Datenbank funktioniert.
das war ungenau von mir - hatte alles hier im Editor direkt im Forum geschrieben. Nun aber die aktuelle Version - - mit dem Inline im Admin gefällt mir die Version mit Abstand besser:

models.py

Code: Alles auswählen

class Location(models.Model):
    zip_code = models.Integerfield()
    start = models.DateTimeField()

    def __str__(self):
        return '{} // {}'.format(self.zip, self.start)

    class Meta:
    	unique_together = [['zip_code','start']]


class Event(models.Model):
	time = models.DateTimeField()
	weather = models.CharField(max_length=2, choices=WATHER)
	people_count = models.IntegerField(default = 0)
	car_count = models.IntegerField(default = 0)
	crash = models.BaseConstraint(default=False)
	location = models.ForeignKey(Event, null=True, blank=True, on_delete=models.CASCADE)

	class Meta:
		unique_together = [['time','location']]
admin.py

Code: Alles auswählen

class Event(admin.TabularInline):
	model = Event


class LocationAdmin(admin.ModelAdmin):
	inlines = [Event]

admin.site.register(Location, LocationAdmin)
Gibt es hier noch einen groben Fehler, den man so lieber niemals macht?
Vom Handling in Django-Admin her gefällt mir das auch wesentlich besser!

Ich ziehe bei der Location gerne einen Startpunkt mit. Es ist zwar nur ein konstruiertes Beispiel, aber es können ja einige Statistiken in Planung sein und noch keine Events beeinhalten.

Re: Models

Verfasst: Mittwoch 11. September 2019, 18:42
von __blackjack__
Es kann `Event`\s ohne `Location` geben? `crash` hat den Typ `BaseConstraint`? What is `WATHER`?