1対1の関係:ユーザーモデルをDjangoのカスタムプロファイルモデルにリンクする

記事の翻訳は、コース「PythonのWeb開発者」の開始を見越して作成されました






Pff ...データベースをもう一度?







リレーショナルデータベースには、次の3つの主要な関係があります。



  • 1対1の関係。
  • 1対多の関係。
  • 多対多の関係。


この記事では、これらの最初の1対1の関係について説明します。



通常、Djangoにはフレームワークに付属するユーザーモデルがすでにあります。独自のフィールド、メソッド、属性などが付属しています。このユーザーモデルの欠点は、Djangoですでに提供されているデフォルト以外にカスタムフィールドを追加できないことです。開発者は、認証されたユーザーのグループからユーザー/クライアントプロファイルを完全に構成する必要がある場合があるため、これは深刻な問題になる可能性があります。たとえば、ブログサイトには、ユーザーの写真、連絡先アドレス、趣味、ニッチなどを含む作成者プロファイルが必要な場合があります。また、Djangoに付属のユーザーモデルではこれができません。



この問題を解決するために、開発者はカスタムプロファイルモデルを作成し、1対1の関係を使用してDjangoのデフォルトのユーザーモデルに接続します。たまたま、ユーザーは1つのプロファイルに接続されていることが保証されており、その逆も同様です。さらに、このメカニズムにより、プロファイルモデルのカスタマイズをより適切に制御できます。



次に、Djangoでこれを行う方法を説明します。



1.デフォルトのDjangoユーザーモデル

を使用するプロファイルを作成するアプリケーションで、新しいforms.pyファイルを作成します。でforms.py、以下のモジュールをインポートします。



from django.contrib.auth.forms import UserCreationForm
from django.contrib.auth.models import User


から継承するクラスを作成しますUserCreationFormこのクラス内に、2つの変数を持つ別のメタクラスを作成します:modelfields変数modelはユーザーモデルを保持し、変数fields作成されるフォームフィールドを保持します。



class createUserForm(UserCreationForm):
    class meta:
        model = User
        fields = ['username', 'password1', 'password2']


上記のコードは、ユーザー名、パスワード、およびパスワード確認用のフィールドを持つフォームを作成します。



2.カスタムユーザープロファイルモデルを作成します。models.py



ファイル、デフォルトのユーザーモデルをインポートします。



from django.contrib.auth.models import User


次に、独自のプロファイルモデルを作成し、Djangoのデフォルトのユーザーモデルと1対1の関係を持つユーザーフィールドを作成する必要があります。



class Profile(models.Model):
    user = models.OneToOneField(User, on_delete=models.CASCADE, null=True,)
    name = models.CharField(max_length=200, null=True)
    email = models.CharField(max_length=200, null=True)
    address = models.CharField(max_length=200, null=True)

    def __str__(self):
        return self.name


3.プロファイルモデルの形状を作成します。form.py



ファイル開き、models.pyからプロファイルモデルをインポートします。また、プロファイルフォームを作成するときに役立つ他のインポートをいくつか追加します。



from django import forms
from django.utils.translation import ugettext_lazy as _
from .models import Profile


次に、から継承するクラスを作成しますforms.ModelFormこのクラスで、2つの変数を含む別のメタクラスを作成します:modelfields変数にmodelは、プロファイルモデルとfields、作成されるフォームフィールドが含まれます。



class profileForm(forms.ModelForm):
    class Meta:
        model = Profile
        fields = ['name', 'email', 'address']
#The labels attribute is optional. It is used to define the labels of the form fields created   
        labels = {
                "name": _("Name     "),
                "email": _("Email Address"),
                "address": _("Street Address"),
                }


フォームの準備ができたので、テンプレートにレンダリングする前にviews.pyでロジックを定義します。



4.ロジックをviews.pyに追加しますforms.pyで



作成されたフォームを操作するには、それらをviews.pyにインポートし、ロジックの作成に役立つモジュールをさらにいくつか追加する必要があります



from django.shortcuts import render, redirect
from django.contrib.auth import authenticate, login,
from django.contrib import messages
from .models import Profile
from .forms import createUserForm, profileForm


それでは、登録ページを作成しましょう。それをregisterPageと呼びましょう空のコンテキスト辞書を作成して、レンダリングを返しましょう。



def registerPage(request):    
    context = {}
    return render(request, 'app_name/register.html', context)


POSTメソッドを呼び出して、フォームから変数に値を割り当てましょう。次に、変数をコンテキスト辞書に渡します。



def registerPage(request):
    if request.method == 'POST':
        form = createUserForm(request.POST)
        profile_form = profileForm(request.POST)

    context = {'form': form, 'profile_form': profile_form}
    return render(request, 'app_name/register.html', context)


次に、両方のフォームを検証し、後で保存します。



def registerPage(request):
    if request.method == 'POST':
        form = createUserForm(request.POST)
        profile_form = profileForm(request.POST)

        if form.is_valid() and profile_form.is_valid():
            user = form.save()

            #we don't save the profile_form here because we have to first get the value of profile_form, assign the user to the OneToOneField created in models before we now save the profile_form. 

            profile = profile_form.save(commit=False)
            profile.user = user

            profile.save()

    context = {'form': form, 'profile_form': profile_form}
    return render(request, 'app_name/register.html', context)


フォームの値が検証されて保存されると、成功メッセージが表示され、ユーザーがログインページにリダイレクトされます。



def registerPage(request):
    if request.method == 'POST':
        form = createUserForm(request.POST)
        profile_form = profileForm(request.POST)

        if form.is_valid() and profile_form.is_valid():
            user = form.save()

            #we don't save the profile_form here because we have to first get the value of profile_form, assign the user to the OneToOneField created in models before we now save the profile_form. 

            profile = profile_form.save(commit=False)
            profile.user = user

            profile.save()

            messages.success(request,  'Your account has been successfully created')

            return redirect('login')

    context = {'form': form, 'profile_form': profile_form}
    return render(request, 'app_name/register.html', context)


5.テンプレートをレンダリングする



ファイルでregister.html、POSTメソッドを使用actionし、空の文字列値を使用してフォームタグを作成します。フォームタグcsrf_tokenでは、それをdjangoテンプレート形式で配置し、フォーム(ユーザーフォームとプロファイルフォーム)を動的にレンダリングします。また、送信ボタンも忘れないでください。



<form method="POST" action="">
                {% csrf_token %}
                    <h3>Register Profile</h3>

                    <div class="form-field">
                        {{profile_form.name.label_tag}}
                        {{profile_form.name}}
                    </div>
                    <div class="form-field">
                        {{form.username.errors}}
                        {{form.username.label_tag}}
                        {{form.username}}
                    </div>
                    <div class="form-field">
                        {{profile_form.email.label_tag}}
                        {{profile_form.email}}
                    </div>
                    <div class="form-field">
                        {{profile_form.address.label_tag}}
                        {{profile_form.address}}
                    </div>
                    <div class="form-field">
                        {{form.password1.errors}}
                        {{form.password1.label_tag}}
                        {{form.password1}}
                    </div>
                    <div class="form-field">
                        {{form.password2.errors}}
                        {{form.password2.label_tag}}
                        {{form.password2}}
                    </div>

                <hr>
                <input id="form-button" class="btn btn-success btn-block" type="submit" value="Create Profile">
                <br>
                    {{form.non_field_errors}}
                <p>Already have an account? <a href="{% url 'login' %}">Login</a></p>
            </form>


フォームに記入して検証して保存した後、ログインページにリダイレクトされるため、操作の成功に関するメッセージが、「アカウントをお持ちではありませんか?」という碑文の直前のログインページに表示されます。登録 "



 <form method="POST" action="">
                   ...
                 <hr>
                <input id="form-button" class="btn btn-success btn-block" type="submit" value="Login">
                
                {% for message in messages %}
                <p>{{message}}</p>
                {% endfor %}
                <p>Don't have an account? <a href="{% url 'store:register' %}">Register</a></p>
            </form>


これは、1対1の関係でユーザーモデルにリンクされているサイトのプロファイルモデルを作成する方法です。








All Articles