Django: enregistrez l'agent utilisateur et gérez-le avec l'administrateur

Création de projet

startproject

(v17)hdknr@wzy:~/ve/v17/src$ mkdir -p ua/web
(v17)hdknr@wzy:~/ve/v17/src$ django-admin startproject app ua/web
(v17)hdknr@wzy:~/ve/v17/src$ cd ua/web
(v17)hdknr@wzy:~/ve/v17/src/ua/web$ python manage.py migrate
(v17)hdknr@wzy:~/ve/v17/src/ua/web$ python manage.py createsuperuser

Ajouter des comptes

(v17)hdknr@wzy:~/ve/v17/src/ua/web$ python manage.py startapp accounts

app/settings.py

INSTALLED_APPS += (
    'accounts',
)

app/urls.py

    url(r'^accounts/', include('accounts.urls')),

accounts/urls.py

from django.conf.urls import patterns, url
import views

urlpatterns = patterns(
    '',
    url(r'login/$', 'django.contrib.auth.views.login'),
    url(r'profile/$', views.profile),
)

accounts/views.py

from django.contrib.auth.decorators import login_required
from django.template.response import TemplateResponse

import models


@login_required
def profile(request):
    ua = None
    return TemplateResponse(
        request,
        'registration/profile.html',
        dict(request=request, ua=ua, ))

accounts/templates/registration

(v17)hdknr@wzy:~/ve/v17/src/ua/web$ mkdir -p accounts/templates/registration
<form method="post">{% csrf_token %}
{{ form.as_p }}
<input type="submit" />
</form>
{{ request.user }}
{{ ua }}

--À ce stade, cela fonctionne jusqu'à la connexion

Modèle UserAgent

Jugement UA (comptes / ua.py)

--agent_type (): recherche un agent correspondant avec une expression canonique

import re


DETECTOR = [
    # Featured Phone
    r'(?P<agent>DoCoMo)',
    r'(?P<agent>SoftBank)',
    r'^(?P<agent>KDDI)',     # if no KDDI, HDML browser.
    r'(?P<agent>Vodafone)',

    ....
]


def agent_type(agent_string):
    for d in DETECTOR:
        m = re.search(d, agent_string, flags=re.IGNORECASE)
        m = m and m.groupdict() or {}
        if m:
            return m['agent'].lower().replace('-', '').replace(' ', '')
    return "generic"

Modèles (accounts / models.py)

from django.db import models
from django.contrib.auth.models import User
from django.utils.translation import ugettext_lazy as _

from ua import agent_type
import hashlib

class UserAgent(models.Model):
    agent = models.CharField(
        _(u'User Agent'),
        max_length=30, default="PC")
    key = models.CharField(
        _(u'User Agent Header MD5 Hash'),
        max_length=40, unique=True, db_index=True,)
    header = models.CharField(
        _(u'User Agent Header'),  max_length=512, )
    users = models.ManyToManyField(
        User, default=None, null=True, blank=True)


    @classmethod
    def get_ua(cls, ua_header, user=None):
        ua, created = cls.objects.get_or_create(
            key=hashlib.md5(ua_header).hexdigest())

        if created:
            ua.agent = agent_type(ua_header)
            ua.header = ua_header
            ua.save()

        if user:
            ua.users.add(user)

        return ua

    def __unicode__(self):
        return "%s(%s)" % (self.agent, getattr(self, 'id', ''))

Enregistrer dans / accounts / profile (acounts / views.py)

--Profil fixe ()

@login_required
def profile(request):
    ua = models.UserAgent.get_ua(
        request.META.get('HTTP_USER_AGENT', 'N/A'),
        request.user)

    return TemplateResponse(
        request,
        'registration/profile.html',
        dict(request=request, ua=ua, ))

Mon grand

(v17)hdknr@wzy:~/ve/v17/src/ua/web$ python manage.py makemigrations accounts
Migrations for 'accounts':
  0001_initial.py:
    - Create model UserAgent
(v17)hdknr@wzy:~/ve/v17/src/ua/web$ python manage.py migrate  accounts
Operations to perform:
  Apply all migrations: accounts
Running migrations:
  Applying accounts.0001_initial... OK

accounts/admin.py

from django.contrib import admin
import models


class UserAgentAdmin(admin.ModelAdmin):
    list_display = tuple(
        [f.name for f in models.UserAgent._meta.fields
         if f.name not in ['key']]
    )

admin.site.register(UserAgent, UserAgentAdmin)

Personnalisation de l'administrateur

UserAgentAdmin(accounts/admin.py)

1. Filtrer par champ d'agent

    list_filter = ('agent', )    

2. Rendre le champ des utilisateurs non modifiable

    add_exclude = ('users',)
    edit_exclude = ('users',)

    def add_view(self, *args, **kwargs):
        self.exclude = getattr(self, 'add_exclude', ())
        return super(UserAgentAdmin, self).add_view(*args, **kwargs)

    def change_view(self, *args, **kwargs):
        self.exclude = getattr(self, 'edit_exclude', ())
        return super(UserAgentAdmin, self).change_view(*args, **kwargs)

3. Affichez le nombre d'utilisateurs connectés avec UserAgent et créez un lien vers la liste

from django.core.urlresolvers import reverse
    list_display = tuple(
        [f.name for f in models.UserAgent._meta.fields
         if f.name not in ['key']]
    ) + ('users_count',)

    def users_count(self, obj):
        if not obj.users.exists():
            return '0'

        uri = reverse("admin:%s_changelist" % obj.users.model._meta.db_table)
        query = "?useragent__id__exact=%d" % (obj.id)
        return mark_safe(
            u"<a href='%s'>%d Users</a>" % (uri + query, obj.users.count()))

    users_count.allow_tags = True

image

4. Au lieu de ne pas modifier le champ des utilisateurs, affichez un lien vers l'utilisateur connecté

    readonly_fields = ('ua_users', )

    def ua_users(self, instance):
        try:
            return ",".join([
                mark_safe('<a href="%s">%s</a>   ' % (
                    reverse("admin:%s_change" % u._meta.db_table, args=[u.id]),
                    u.__unicode__()))
                for u in instance.users.all()])
        except:
            return "errors"

    ua_users.short_description = "UserAgent Users"
    ua_users.allow_tags = True

image

UserAdmin(accounts/admin.py)

from django.db.models.manager import Manager
from django.utils.safestring import mark_safe
from django.contrib.auth.admin import UserAdmin
def link_to_relation(self, obj, field=""):
    fobj = obj and getattr(obj, field, None)

    if fobj is None:
        return "No Link"

    if issubclass(fobj.__class__, Manager):
        fobj = fobj.all()
    else:
        fobj = [fobj, ]

    return mark_safe("<br/>".join([
        '<a href="%s">%s</a>' % (
            reverse("admin:%s_change" % ln._meta.db_table, args=[ln.id]),
            ln.__unicode__()
        ) for ln in fobj]))

--Créez un backlink avec l'objet User et useragent_set

useragent_link = lambda self, obj: link_to_relation(self, obj, "useragent_set")
useragent_link.short_description = u"User Agent"
useragent_link.allow_tags = True

--Ajouter ceci à UserAdmin

UserAdmin.list_display = tuple(
    set(UserAdmin.list_display + ('useragent_link', )))
UserAdmin.useragent_link = useragent_link
UserAdmin.list_filter = UserAdmin.list_filter + ('useragent__agent',)

――Vous pouvez revenir avec ça

image

Recommended Posts

Django: enregistrez l'agent utilisateur et gérez-le avec l'administrateur
HTTPS avec Django et Let's Encrypt
Gérer les fichiers de configuration Django avec Python-decouple
CentOS 6.4, Python 2.7.3, Apache, mod_wsgi, Django
Création de carte Ramen avec Scrapy et Django
Enregistrer le dernier accès de l'utilisateur avec Redis
Gérer les images Django et les actifs statiques sur Ubuntu
Générer et publier des données d'image factice avec Django
Gérez de manière déclarative l'environnement avec Nix et home-manager
Gérez les transitions d'état et communiquez avec les compteurs intelligents
Internationalisation avec Django
CRUD avec Django
Enregistrez la température et l'humidité avec systemd sur Raspberry Pi
Plus de nouvelles méthodes d'authentification des utilisateurs avec Django REST Framework
Créer une API autour de l'authentification des utilisateurs avec Django REST Framework
Implémentez l'extension utilisateur Django et enregistrez les informations jointes
Obtenir les informations de localisation actuelles et l'agent utilisateur en Python
Gérez les packages d'exécution Python et les packages d'environnement de développement avec Poetry
[Python] Obtenez des informations sur les utilisateurs et des articles sur l'API de Qiita