2017-01-22 3 views
0

Ich habe ein Modell, das Daten aus einer Tabelle in einer Datenbank abruft, und zwei andere Modelle (Streets und Cities), die Daten aus zwei anderen Tabellen abrufen. All diese Informationen müssen vom Modell LandVehicle abgerufen werden. Ich habe einige Probleme herauszufinden, genau wie die Daten aus den anderen Tabellen in die Eigenschaften im LandVehicle Modell abrufen. Unten ist die Klassenstruktur mit arbeite ich:Modelleigenschaften, die leer sind

class Vehicle(models.Model): 

    name = models.CharField(max_length=500) 
    lat = models.DecimalField(max_digits=15,decimal_places=6) 
    lon = models.DecimalField(max_digits=15,decimal_places=6) 
    radius = Decimal(.06) 

    @abstractproperty 
    def streets(self): 
     pass 

    @abstractproperty 
    def cities(self): 
     pass 

    @cached_property 
    def nearby_vehicles(self): 
     return Vehicle.objects.filter(lat__range=[self.lat - 2, self.lat + 2], lon__range=[self.lon - 2, self.lon + 2]) 

    # Meta 
    class Meta: 
     abstract = True 


class LandVehicle(Vehicle): 

    @property 
    def streets(self): 
     name_substr = self.name 
     if " " in name_substr: 
      name_substr = name_substr[:name_substr.index(" ")] 

     return LandVehicle.objects.filter(Q(streets__name__contains=self.name) | 
              Q(streets__name__contains=name_substr) | 
              (Q(streets__lat__range=[self.lat - self.radius, self.lat + self.radius]) & 
              Q(streets__lon__range=[self.lon - self.radius, self.lon + self.radius]))) 

    @property 
    def cities(self): 
     name_substr = self.name 
     if " " in name_substr: 
      name_substr = name_substr[:name_substr.index(" ")] 

     return LandVehicle.objects.filter(Q(cities__name__contains=self.name) | 
              Q(cities__name__contains=airport_name_substr) | 
              (Q(cities__lat__range=[self.lat - self.radius, self.lat + self.radius]) & 
              Q(cities__lon__range=[self.lon - self.radius, self.lon + self.radius]))) 

    # Meta 
    class Meta: 
     db_table = 'landvehicles' 

class Streets(models.Model): 
    # Meta 
    class Meta: 
     db_table = 'streets' 

class Cities(models.Model): 
    # Meta 
    class Meta: 
     db_table = 'cities' 

muß ich einen Fehler nicht aus dem Weg es jetzt eingerichtet ist, aber die Daten in der Ansicht, wie vehicle.streets zugreifen, wenn vehicle eine ist Instanz von LandVehicle, ist nur eine leere Variable.

Ich verstehe, dass ich die Daten analysieren muss, sobald ich es abrufen kann, aber im Moment scheint es nichts abzurufen (kann auch nichts ausdrucken).

Bearbeiten/Update:

den self Parameter an jede der Eigenschaften (geändert oben) Durch das Hinzufügen, erhalte ich eine Fehlermeldung:

Cannot resolve keyword 'streets' into field. Choices are: id, lat, lon, name 

Wenigstens habe ich eine Art von Fehler bekommen , aber ich weiß immer noch nicht, wie ich auf die Eigenschaften zugreifen soll.

+0

durch leere Variable, die Sie bedeuten 'None'? Versuchen Sie, einige '' '' '' '' '' '' '' '' ''zu drücken, um zu sehen, ob der Code überhaupt ausgeführt wird. Auch der Code sieht komisch aus - Ihren Methoden fehlt "self" (als erster Parameter) überall. – yedpodtrzitko

+0

@yedpodtrzitko Wenn ich versuche, Text auf der Konsole innerhalb der Eigenschaften zu drucken (z. B. "Test" in der 'streams()' Eigenschaft), funktioniert es, so scheint es ausgeführt werden, aber wenn ich die Abfrage innerhalb der zuweisen Eigenschaft auf eine Variable und drucken, dass nichts auf die Konsole druckt.Ich habe die fehlenden 'self' Parameter zu jeder der Eigenschaften hinzugefügt und den Beitrag mit weiteren Informationen über den Fehler aktualisiert. – swiftsly

Antwort

1

Ah natürlich, jetzt sehe ich es. Der Fehler sagt es - Sie versuchen, streets als eine Spalte in Ihrem filter() Ausdruck zu verwenden, aber es ist keine DB-Spalte irgendwo definiert. Sie müssen die Spalte als Vorfahr der Klasse Field definieren (+ eine Migration dafür vornehmen) und dann in Ihrer Datenbankabfrage verwenden.

Sie müssen auch die Eigenschaft streets so etwas anderes umbenennen, wenn die db-Spalte auf diese Weise aufgerufen wird.

Bearbeiten Sie für den Kommentar unten: Sie können beide Dinge haben, aber sie können natürlich nicht den gleichen Namen haben. So zum Beispiel so:

class Vehicle(models.Model): 

    # ... 
    # a singular name 
    street = models.CharField(max_length=128) 

    @property 
    def streets(self): # plural 
     # you can use this instead of the 3 lines with `if` you have now 
     name_substr = self.name.split()[0] 

     #since the column is singular `street`, is needs to be singular in the query below too. 
     return LandVehicle.objects.filter(Q(street__name__contains=self.name) | 
              Q(street__name__contains=name_substr) | 
              (Q(street__lat__range=[self.lat - self.radius, self.lat + self.radius]) & 
              Q(street__lon__range=[self.lon - self.radius, self.lon + self.radius]))) 

Was Ihre Frage, was tut LandVehicle.objects.filter(), ist, dass es eine praktische Möglichkeit ist eine SQL-Abfrage, ohne tatsächlich das Schreiben der rohe SQL-Abfrage zu schreiben. Django übersetzt es dann in die Abfrage für Sie. Wenn Sie also die Datenbankdatensätze nach einem Straßennamen filtern möchten, müssen Sie die Spalte street in der Datenbank haben, damit die Datenbank den Vergleich über den Daten durchführen kann.

Zum Beispiel wird dieses Bit: Q(street__name__contains='foobar') in eine SQL-Abfrage wie select * from vehicle where street LIKE '%foobar%' übersetzt. Es wird also offensichtlich erwartet, dass die Spalte street da sein muss. Nicht nur zum Filtern der Daten, sondern Sie müssen diese Daten auch speichern.

Wenn Sie verstehen nicht, wie Django ORM funktioniert, gehen diesen Teil der Dokumentation lesen: https://docs.djangoproject.com/en/1.10/topics/db/queries/

+0

Es macht allmählich Sinn, aber ich muss völlig verwirrt sein, was 'LandVehicle.objects.filter (Q (cities__name__contains = self.name)') tut.Wie Sie darauf hingewiesen haben Straßen ist keine Spalte, aber das Endziel ist für 'strips', um eine Liste von Tabellenzeilen (mit all ihren Spaltendaten) zu halten, um sie in ein Tupel zu parsen. Um das klarzustellen, sollte ich ein benutzerdefiniertes Feld erstellen, das als eine Art Container für alle fungiert die Zeilendaten? – swiftsly

Verwandte Themen