web-dev-qa-db-ja.com

適切にカスタマイズする方法Django LoginView

ユーザーがその日に初めてログオンするかどうかに基づいて、Django LoginViewをカスタマイズする方法を理解しようとしています。現在LoginViewを設定して、デフォルトでLOGIN_REDIRECT_URL = "book:author" in my settings.py file。これは問題なく機能します。ユーザーがログインして正常に認証されると、期待どおりに "book:author"にリダイレクトされます。

私がやろうとしているのは、ユーザーがその日に初めてログインした場合は、ユーザーを1つのURLにリダイレクトし、その日のその他のログイン反復の場合は、別のURLにリダイレクトすることです。条件付きURLリダイレクトではなくメッセージングを使用してNEXTパラメーターを使用する方法について、さまざまな方法について読みました。これを行うための最良かつ最も安全で適切な方法を見つけようとしています。

これが私のデフォルトのLoginViewです...(特別なことは何もありません)

class LoginView(LoginView):
    template_name = 'registration/login.html'
    form_class = AuthenticationForm

そしてそれは私のsettings.pyファイル定義に基づいてリダイレクトします...

    LOGIN_REDIRECT_URL = "book:author" 

その日の最初のログインを別のURLにリダイレクトする最良の方法は何ですか?

提案を事前に感謝します。

私はこれを見つけましたSO回答 Django-条件付きログインリダイレクト そしてそれは私が探しているもののようです。下部の例を使用することの欠点はありますか? ?

そして、関数ベースの例とは対照的に、LoginViewをどのように使用するのですか?

3
Steve Smith

あなたの質問に答えるために、ある意味でこのモデルに似たクライアントモデルがあり、ユーザーのログインを保存するヘルパーモデルが必要だとしましょう。

models.py:

from Django.db import models
from Django.contrib.auth.models import User

class Client(models.Model):
    """
    This client model is pointing to Django's User model
    You can use your custom user model using AbstractBaseUser or whatever.
    And if you're using Django's User model directly, this class is not required
    """
    user = models.OneToOneField(
        User,
        on_delete=models.DO_NOTHING,
        verbose_name='User',
        related_name='cli',  # related name manager if needed
        null=False,
        blank=False,
    )

    def __str__(self):
        return '{}'.format(self.user.username)


class ClientLogins(models.Model):
    """
    This is a helper model table that stores the logins dates of the client
    """
    client = models.ForeignKey(
        Client,
        verbose_name='Client',
        on_delete=models.DO_NOTHING
    )
    date = models.DateTimeField(verbose_name="Date login")

    def __str__(self):
        return '{}'.format(self.client)

次に、フォーム:

forms.py:

class LoginForm(forms.ModelForm):
    '''Simple login form'''
    class Meta:
        model = User
        fields = ('username', 'password')

そして最後に、ログイン動作はビュークラス/関数で処理する必要があります。

views.py:

from datetime import timedelta
from Django.utils import timezone
from MY_APP import models, forms

class LoginUser(LoginView):
    template_name = 'login.html'  # your template
    from_class = forms.LoginForm  # your form

    def get_success_url(self):
        '''Here the part where you can implement your login logic'''
        now = timezone.now()
        # Get current day date object
        # like: 12/02/2019 00:00:00
        today = now.replace(minute=0).replace(second=0).replace(microsecond=0)
        # Get the client from the user object
        client = self.request.user.cli
        # Get all the user today's logins and count them
        client_logins = models.ClientLogins.objects.filter(
            client=client,
            date__gte=today,
            date__lte=today + timedelta(days=1)
        ).count()
        if client_logins < 1:  # Or: if not client_logins:
            # create a login tracker record
            models.ClientLogins.objects.create(
                client=client,
                date=now  # Store the date where the user logged in the website
            )
            return reverse_lazy('FIRST_LOGIN_REDIRECT_URL')
        # Or redirect to: settings.LOGIN_REDIRECT_URL
        return super().get_success_url()

詳細については、これが LoginView のコアコードです。このように、MROリストと、目的の動作を実現するためにオーバーライドできるものを知ることができます。

2
Chiheb Nexus