質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

87.49%

Django プロフィール機能の実装について

受付中

回答 1

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 298

前提・実現したいこと

現在制作しているもの

Django+Reactでtwitterのクローンアプリを制作しています。
現段階でカスタムユーザモデルを使って、ユーザ登録機能、ログイン機能、ログアウト機能を実装しました。
次の段階でプロフィール機能を実装しようとしています。

質問内容

プロフィール機能を実装しようとして、コードを書いたはいいですが、adminの管理画面でデータを入れようとしたら、エラーが出てそれ以降全く解決しませんでした。なにか解決方法はありますでしょうか?また、プロフィールの情報入力画面でも同様のエラーが起きました。

実現したいこと

カスタムユーザを使ったプロフィールの作成機能、編集機能、閲覧機能を追加したいです。

発生している問題・エラーメッセージ

イメージ説明

申し訳ありません。文字数制限でエラーコードが載せられなかったので、スクショになります

該当のソースコード

//accounts/models.py

import uuid
from django.db import models
from django.core.mail import send_mail
from django.contrib.auth.models import PermissionsMixin
from django.contrib.auth.base_user import AbstractBaseUser
from django.utils.translation import ugettext_lazy as _
from django.utils import timezone
from django.contrib.auth.base_user import BaseUserManager
from django.db.models.signals import post_save
from django.dispatch import receiver
from profiles.models import Profiles


class UserManager(BaseUserManager):
    """ユーザーマネージャー."""

    use_in_migrations = True

    def _create_user(self, email, password, **extra_fields):
        """Create and save a user with the given username, email, and
        password."""
        if not email:
            raise ValueError('The given email must be set')
        email = self.normalize_email(email)

        user = self.model(email=email, **extra_fields)
        user.set_password(password)
        user.save(using=self._db)
        return user

    def create_user(self, email, password=None, **extra_fields):
        extra_fields.setdefault('is_staff', False)
        extra_fields.setdefault('is_superuser', False)
        return self._create_user(email, password, **extra_fields)

    def create_superuser(self, email, password, **extra_fields):
        extra_fields.setdefault('is_staff', True)
        extra_fields.setdefault('is_superuser', True)

        if extra_fields.get('is_staff') is not True:
            raise ValueError('Superuser must have is_staff=True.')
        if extra_fields.get('is_superuser') is not True:
            raise ValueError('Superuser must have is_superuser=True.')

        return self._create_user(email, password, **extra_fields)


class User(AbstractBaseUser, PermissionsMixin):
    """カスタムユーザーモデル."""
    user_id = models.CharField(default=uuid.uuid4,
                            primary_key=True, editable=False,max_length=36)

    email = models.EmailField(_('email address'), unique=True)

    username = models.CharField(_('ニックネーム'), max_length=150, blank=True)

    is_staff = models.BooleanField(
        _('staff status'),
        default=False,
        help_text=_(
            'Designates whether the user can log into this admin site.'),
    )
    is_active = models.BooleanField(
        _('active'),
        default=True,
        help_text=_(
            'Designates whether this user should be treated as active. '
            'Unselect this instead of deleting accounts.'
        ),
    )
    date_joined = models.DateTimeField(_('date joined'), default=timezone.now)

    objects = UserManager()

    EMAIL_FIELD = 'email'
    USERNAME_FIELD = 'email'
    REQUIRED_FIELDS = []

    class Meta:
        verbose_name = _('user')
        verbose_name_plural = _('users')

    def get_full_name(self):
        full_name = '%s' % (self.username)
        return full_name.strip()

    def get_short_name(self):
        """Return the short name for the user."""
        return self.username

    def email_user(self, subject, message, from_email=None, **kwargs):
        """Send an email to this user."""
        send_mail(subject, message, from_email, [self.email], **kwargs)

@receiver(post_save,sender=User)
def create_profile(sender,**kwargs):
    if kwargs['created']:
        user_profile = Profiles.objects.get_or_create(user=kwargs['instance'])

//profiles/models.py

from django.db import models
from django.contrib.auth import get_user_model
from django.db.models.signals import post_save
from django.utils import timezone
from django.conf import settings

# Create your models here.
User = settings.AUTH_USER_MODEL
class Profiles(models.Model):

    user = models.OneToOneField(settings.AUTH_USER_MODEL,primary_key=True,on_delete=models.CASCADE,related_name='profile')
    account_id = models.CharField(max_length=255,unique=True,null=True,blank=True)
    location = models.CharField(max_length=220,null=True,blank=True)
    bio = models.TextField(blank=True,null=True)
    timestap = models.DateTimeField(auto_now_add=True)
    update_at = models.DateTimeField(auto_now = True)
    icon = models.ImageField(upload_to="images",blank=True,null=True)
    header_img = models.ImageField(upload_to="images",blank=True,null=True)


    def __str__(self):
        return self.account_id


//profiles/forms.py

from .models import Profiles
from django import forms


class ProfilesForm(forms.ModelForm):


    class Meta:
        model = Profiles
        fields = ["account_id","location","bio","icon","header_img"]
        label = {"account_id":"アカウント ID","location":"場所","bio":"自己紹介","icon":"アイコン","header_img":"ヘッダー画像"}
    def save(self):
        data = self.cleaned_data
        profile = Profiles(
            account_id=data['account_id'],
            location=data['location'],
            bio = data['bio'],
            icon= data['icon'],
            header_img = data['header_img'],
        )

        profile.save()


//profiles/urls.py

from django.urls import path
from .views import ProfileCreateView,ProfileView

app_name = "profiles"
urlpatterns=[
    path('profile/<slug:pk>',ProfileView.as_view(),name='detail'),
    path('profile/myprofile/<slug:pk>',ProfileCreateView.as_view(),name='edit'),
]


//profiles/views.py

from django.shortcuts import render,redirect

from django.contrib.auth import get_user_model
from django.views.generic import CreateView,FormView,TemplateView
from django.contrib.auth.mixins import LoginRequiredMixin
from .models import Profiles
from .forms import ProfilesForm
from django.contrib import messages


User = get_user_model()

class ProfileCreateView(LoginRequiredMixin,CreateView):
    model = Profiles
    form_class = ProfilesForm
    template_name = "profiles/profileedit.html"
    success_url = "profiles/profileedit.html"

    def form_valid(self,form):
        form.save()
        messages.success(self.request,"保存しました")
        return super().form_valid(form)

    def form_invalid(self,form):
        messages.warning(self.request,"保存できませんでした")
        return super().form_invalid(form)


class ProfileView(LoginRequiredMixin,TemplateView):
    template_name = "profiles/profile.html"


    def get_queryset(self):
        return Profiles.objects.filter(user=self.request.user)

試したこと

-forms.pyで使用するform.Model,forms.Formのどちらも試した
-views.pyにて、関数ベースビュー、クラスベースビューどちらも試しました。
-マイグレーションをやり直しました。

ここにより詳細な情報を記載してください。

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 1

0

OneToOneFieldで定義されていて、PrimaryKeyとして使っているので、
Userは必ずProfile保存時に定義しないといけないのかなと思います。
下記のプロフィールモデル作成時にユーザー情報も一緒に入れてデータ作成するといかがでしょうか?

profile = Profiles(
            #ここにユーザーを追加
            account_id=data['account_id'],
            location=data['location'],
            bio = data['bio'],
            icon= data['icon'],
            header_img = data['header_img'],
        )

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2021/05/30 16:41 編集

    ご回答、ありがとうございます。疑問なのですが、formの方にユーザ情報を入れるというのは、
    具体的にどのようにすればいいでしょうか

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 87.49%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る