Für die Aufbewahrung der Zustände der Elementen werden manchmal die Bitmasken verwendet. Zum Beispiel, als Zustände - gelesener/ungelesener Kommentar zu einem Artikel für einzelnen Benutzer. Obwohl es für diesen konkreten Fall besser wäre, die Uhrzeit/das Datum des letzten Besuchs eines Artikels aufzubewahren, hier können aber auch andere Aufgaben aufkommen, in denen man sich die binären Angaben für die Elemente merken muss, die kein Datum enthalten.

Man kann die M2M-Verbindung zwischen einem User und Objekt verwenden. Ein großer Nachteil ist aber wesentliche Ressourcen für Index und die Einträgeanzahl, wenn es viele Benutzer und Beobachtungsobjekte gibt. Hier ist es sinnvoll die Bitmasken zu verwenden, sie haben keinen solchen Nachteil.

Die Idee ist, dass es nur ein Eintrag in der Databasa für jeden Benutzer gibt, und die Nummer des Bytes in dem Eintrag und die Nummer des Bits in diesem Byte bestimmen den Zustand des bestimmten Elements. Normall hat Django kein Modell, das die blob-Elemente in den Databasen (die binären Daten) unterstützt. Deswegen habe ich das gewöhnliche Textfeld benutzt, ein Symbol dieses Feldes bestimmt den Zustand für vier Elemente. Das heißt, der Eintrag 250 Bytes groß gibt uns die Angaben über den Zustand für 1000 Elemente.

Zum Beispiel, es gibt 10.000 Anekdoten (diese Methode ist angebracht, wenn es viele Elemente gibt, das heißt, die Artikel sind eher klein:)
Möge es 100.000 Benutzer geben. Dann sieht unser Verbindungsmodell etwa so aus:
class Readed(models.Model):
  user = models.ForeignKey(User, related_name='readed')
  readed_flags = models.TextField(blank=True)
Die Einträgeanzahl ist gleich der Benutzeranzahl - 100.000.
Und die Größe des readed_flags ist maximum 2500 Bytes (10.000/4).
Mit unserer Lösung braucht man alle 2500 Bytes nicht aufzubewahren, sondern nur die Bytesanzahl, die als die größte ID des gelesenen Artikles geteilt durch 4 bestimmt wird.

In dieser Geschichte haben wir 2 Funktionen: is_readed(id) и set_readed(id)
is_readed(id) gibt den Zustand (true/false) für die bestimmte ID zurück.
set_readed (id) weist dem Zustand "true" zu.
Nach set_readed() darf man nicht vergessen die Änderungen durch save() zu speichern.
Innerhalb der Funktion set_readed() habe ich kein save() durchgeführt, damit es möglich wäre, für große Artikelanzahl die Flage schnell einzuschalten und die Änderungen in die Database auf einmal zu speichern.

Hier ist der Modellcode:
READED_FLAG = [1,2,4,8,0]
class Readed(models.Model):
  user = models.ForeignKey(User, related_name='readed')
  readed_flags = models.TextField(blank=True)

  def dec2hex(self,n):
    return "%X" % n
  
  def hex2dec(self,s):
    return int(s, 16)
  
  def is_readed(self,num):
    if num < 1:
      raise ValueError("Must be positiv and not null")
    byte_position, bit_position = divmod(num-1,4)
    notpresent = byte_position + 1 - len(self.readed_flags)
    if notpresent:
      return False
    four_status = self.hex2dec(self.readed_flags[byte_position])
    return (four_status & READED_FLAG[bit_position]) != READED_FLAG[4]
  
  def set_readed(self,num):
    if num < 1:
      raise ValueError("Must be positiv and not null")
    byte_position, bit_position = divmod(num-1,4)
    notpresent = byte_position + 1 - len(self.readed_flags)
    for i in xrange(notpresent):
      self.readed_flags += "0"
    if notpresent:
      four_status = 0
    else:
      four_status = self.hex2dec(self.readed_flags[byte_position])
    four_status_new = self.dec2hex(four_status|READED_FLAG[bit_position])
    readed_flags_new = self.readed_flags[:byte_position]+ \
                    four_status_new+self.readed_flags[byte_position+1:]
    self.readed_flags = readed_flags_new
Die Anwendung dieser Methode ist viel breiter, als einfach nur Ersatz des M2M-Modells. Es liegt nur an ihrer Fantasie ;)

7 Votes | Average: 4.4 out of 57 Votes | Average: 4.4 out of 57 Votes | Average: 4.4 out of 57 Votes | Average: 4.4 out of 57 Votes | Average: 4.4 out of 5 (7 votes, average: 4.4 out of 5)
Loading ... Loading ...

Top Posts: