Ganz am Anfang der Erstellung von Artikeln und Fragen im Forum habe ich einen einfachen Zähler für Ansichten zu diesem Inhalt hinzugefügt.
Dieser Zähler war ein gewöhnliches Feld vom Integer-Typ und wurde jedes Mal, wenn eine Seite angefordert wurde, um eins erhöht.
Aber vor nicht allzu langer Zeit habe ich diesen Zähler durch ein Zählermodell zum Registrieren eindeutiger Ansichten ersetzt. Ich habe es nur gemacht, weil ich es schöner finde.
Der Zähler zählt eindeutige Besucher entweder nach IP-Adresse, wenn der Benutzer auf der Website nicht autorisiert ist, oder nach Benutzerkonto, wenn dieser Benutzer auf der Website autorisiert ist.
Also lass uns lernen, wie es geht.
Viewer-Modell
Verantwortlich für das Zählen einzelner Benutzer, die die Website angesehen haben.
class Viewer(models.Model): ipaddress = models.GenericIPAddressField("IP address", blank=True, null=True) user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.SET_NULL, blank=True, null=True)
Wie Sie sehen können, gibt es in diesem Modell nur zwei Felder, das erste ist die IP-Adresse und das zweite der Fremdschlüssel für das Benutzermodell
Hinzufügen eines Zählers zum Inhaltsmodell
Und jetzt fügen wir einem Site-Content-Modell einen Zähler hinzu, zum Beispiel dem Artikelmodell Artikel
class Article(models.Model): viewers = models.ManyToManyField(Viewer) # Some another code
Das Hinzufügen von Code erfolgt als Viele-zu-Viele-Beziehung. Da der eindeutige Besucher in diesem Fall einer sein wird, kann er jedoch viele andere Artikel anzeigen. Gleichzeitig kann der Artikel von vielen anderen Nutzern eingesehen werden.
So erhöhen Sie den Inhaltsansichtszähler
Höchstwahrscheinlich ist eine Ansichtsklasse oder Ansichtsfunktion für die Anzeige von Artikeln auf Ihrer Website verantwortlich. Ich persönlich bevorzuge die moderne klassenbasierte Ansicht in Django.
Daher werde ich ein Mixin schreiben, das mit DetailView verwendet werden kann, um eindeutige Ansichten von Inhalten auf der Website zu registrieren.
class CountViewerMixin: def get(self, request, *args, **kwargs): response = super().get(request, *args, **kwargs) if hasattr(self.object, 'viewers'): viewer, created = Viewer.objects.get_or_create( ipaddress=None if request.user.is_authenticated else get_client_ip(request), user=request.user if request.user.is_authenticated else None ) if self.object.viewers.filter(id=viewer.id).count() == 0: self.object.viewers.add(viewer) return response
Aus dem Code ist ersichtlich, dass das Mixin die get-Methode überschreibt, überprüft, ob das Inhaltsobjekt in der Ansicht existiert und erst danach einen eindeutigen Besucher erhält, und nachdem überprüft wurde, dass der Besucher noch nicht unter den Besuchern vorhanden ist, die die angesehen haben Inhalt, fügt ihn den Inhaltsansichten hinzu.
Das Inhaltsobjekt selbst wird also nicht modifiziert, im Gegensatz zum Zähler in Form eines Integer-Felds im Inhaltsmodell. Was den Code tatsächlich verkomplizieren kann, ist, wenn Sie Methoden zum Speichern von Inhaltsmodellen überschreiben oder Empfänger -Funktionen geschrieben haben, um Sicherungssignale vom Modell zu verarbeiten. Beim Viewer -Zähler, der in diesem Artikel vorgestellt wird, funktionieren Signale wie post_save auf dem Inhaltsmodell einfach nicht.
In der Inhaltsansicht sieht die Mixin-Verbindung folgendermaßen aus:
class ArticleView(CountViewerMixin, DetailView): # some another code
Verwendung in Vorlage
Innerhalb der Vorlage können Sie die Anzahl der Ansichten wie folgt abrufen
{{ object.viewers.count }}
get_client_ip
Das Mixin hat auch eine Funktion, um eine IP-Adresse von einer HTTP-Anfrage zu erhalten. Ich habe diese spezielle Funktion zum [Abrufen der IP-Adresse des Benutzers aus einer Anfrage in einem der Artikel] bereits beschrieben (https://evileg.com/ru/post/181/).
Und in meiner neuesten Überarbeitung für Django 3 sieht es so aus.
def get_client_ip(request): """ Get client ip address from HTTP request :param request: HTTP request :return: IP Address """ x_forwarded_for = request.META.get('HTTP_X_FORWARDED_FOR') return x_forwarded_for.split(',')[-1].strip() if x_forwarded_for else request.META.get('REMOTE_ADDR')
Abschluss
Ein solcher Zähler erleichtert die Wartung des Codes, wenn Sie Reaktionen auf das Speichern von Inhalten haben, und verringert auch die Auswirkungen von Cheats auf Inhaltszähler.