سؤال

لدي نموذج ممتد للمستخدم في Django:

class UserProfile(models.Model):
  user = models.ForeignKey(User, unique=True)
  #other things in that profile

وإشارات:

from registration.signals import user_registered
from models import UserProfile
from django.contrib.auth.models import User

def createUserProfile(sender, instance, **kwargs):
  profile = users.models.UserProfile()
  profile.setUser(sender)
  profile.save()

user_registered.connect(createUserProfile, sender=User)

أتأكد من تسجيل الإشارة من خلال وجود هذا في بلدي __init__.py:

import signals

بحيث يجب أن تخلق لي مستخدم جديد لكل مستخدم يسجل، أليس كذلك؟ لكنها لا. أحصل دائما على "استعلام مطابقة UserProfile غير موجود" أخطاء "عندما أحاول تسجيل الدخول، مما يعني أن إدخال قاعدة البيانات ليس هناك.

يجب أن أقول إنني استخدم تسجيل Django، الذي يوفر إشارة المستخدم.

هيكل التطبيقات المهمة لهذا هو، أن لدي تطبيق واحد يسمى "المستخدمين"، هناك ). يتم تعريف فئة UserProfile في Models.py.

تحديث: لقد غيرت الإشارات.

from django.db.models.signals import post_save
from models import UserProfile
from django.contrib.auth.models import User

def create_profile(sender, **kw):
    user = kw["instance"]
    if kw["created"]:
        profile = UserProfile()
        profile.user = user
        profile.save()

post_save.connect(create_profile, sender=User)

ولكن الآن أحصل على "IntegrityError":

"العمود user_id غير فريد"

تحرير 2:

لقد وجدت ذلك. يشبه بطريقة أو بأخرى قمت بتسجيل الإشارة مرتين. الحل البديل لهذا هو موضح هنا: http://code.djangoproject.com/wiki/signals#helppost_saveseemstobeemitttwiceforechsave.

اضطررت إلى إضافة Dispatch_UID، والآن تبدو إشاراتي. تطبيقي مثل هذا ويعمل:

from django.db.models.signals import post_save
from django.contrib.auth.models import User
from models import UserProfile
from django.db import models

def create_profile(sender, **kw):
    user = kw["instance"]
    if kw["created"]:
        profile = UserProfile(user=user)
        profile.save()

post_save.connect(create_profile, sender=User, dispatch_uid="users-profilecreation-signal")
هل كانت مفيدة؟

المحلول

يمكنك تطبيقه باستخدام Post_Save على المستخدم:

from django.db.models.signals import post_save
from models import UserProfile
from django.contrib.auth.models import User

def create_profile(sender, **kwargs):
    user = kwargs["instance"]
    if kwargs["created"]:
        profile = users.models.UserProfile()
        profile.setUser(sender)
        profile.save()

post_save.connect(create_profile, sender=User)

يحرر:
حلا آخر ممكن، الذي تم اختباره ويعمله (أنا أستخدمه على موقعي):

from django.db import models
from django.contrib.auth.models import User
from django.db.models.signals import post_save
def create_profile(sender, **kwargs):
    user = kwargs["instance"]
    if kwargs["created"]:
        up = UserProfile(user=user, stuff=1, thing=2)
        up.save()
post_save.connect(create_profile, sender=User)

نصائح أخرى

يمكنك إنشاء ملف التعريف الموسع عند الوصول إليها لأول مرة لكل مستخدم بدلا من ذلك:

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

class UserProfile(models.Model):
    user = models.ForeignKey(User, unique=True)
    additional_info_field = models.CharField(max_length=50)

User.profile = property(lambda u: UserProfile.objects.get_or_create(user=u)[0])

ثم استخدام

from django.contrib.auth.models import User
user = User.objects.get(pk=1)
user.profile.additional_info_field

المرجع: http://www.codekoala.com/blog/2009/quick-django-tip-user-profiles/

ساعدني هذا: Primary_Key = صحيح

class UserProfile(models.Model):
    user = models.OneToOneField(User, unique=True, primary_key=True, related_name="user")
    phone = models.CharField(('phone'),max_length=30, blank=False, null=True)
    user_building = models.ManyToManyField(Building, blank=True)
    added_by = models.ForeignKey(User, blank=True, null=True, related_name="added")

عندما تتصل profile.setUser(), ، أعتقد أنك تريد المرور instance بدلا من sender كما المعلمة.

من توثيق إشارة المستخدم, sender بالعودة الى User صف دراسي؛ instance هو كائن المستخدم الفعلي الذي تم تسجيله.

وفقا لأحدث بحثي، إنشاء ملف منفصل، على سبيل المثال، Singals.py، لا يعمل.

من الأفضل توصيل "Create_Profile" ب "post_save" في Models.py مباشرة، وإلا فلن يتم تنفيذ هذه القطعة هذه القائمة لأنها في ملف منفصل ولا أحد يستورده.

الرمز النهائي الخاص بك للرجوع اليها:

# models.py

# Here goes the definition of class UserProfile.
class UserProfile(models.Model):
    ...

# Use signal to automatically create user profile on user creation.

# Another implementation:
# def create_user_profile(sender, **kwargs):
#     user = kwargs["instance"]
#     if kwargs["created"]:
#         ...
def create_user_profile(sender, instance, created, **kwargs):
    """
    :param sender: Class User.
    :param instance: The user instance.
    """
    if created:
        # Seems the following also works:
        #   UserProfile.objects.create(user=instance)
        # TODO: Which is correct or better?
        profile = UserProfile(user=instance)
        profile.save()

post_save.connect(create_user_profile,
                  sender=User,
                  dispatch_uid="users-profilecreation-signal")

تحديث لعام 2018:

جمعت هذه السؤال الكثير من المشاهدات، ربما حان الوقت للتحديث.

هذه هي أحدث إصدار لأحدث django.

from django.dispatch import receiver
from django.db.models.signals import post_save
from django.conf import settings
from models import UserProfile

@receiver(post_save, sender=settings.AUTH_USER_MODEL)
def create_user_profile(sender, instance=None, created=False, **kwargs):
    if created:
        UserProfile.objects.create(user=instance)
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top