在django扩展用户模型中发布配置文件信息(用户没有配置文件)

时间:2018-04-17 02:28:01

标签: django

我知道这是一个经常出现的主题,但是,由于网络上的所有可用资源和stackoverflow,我无法让我的表单正常工作。

我收到此错误:Exception Type: RelatedObjectDoesNotExist, Exception Value: User has no profile.

这是我在Django中的设置。

models.py

from django.db import models
from django.contrib.auth.models import User
from django.db.models.signals import post_save
from django.dispatch import receiver

class Profile(models.Model):
    user = models.OneToOneField(User, on_delete=models.CASCADE, related_name='profile')
    location = models.CharField(max_length=30, blank=True)
    birth_date = models.DateField(null=True, blank=True)

    def __str__(self):
        return self.user.username

@receiver(post_save, sender=User)
def create_user_profile(sender, instance, created, **kwargs):
    if kwargs.get('created', False):
         Profile.objects.create(user=kwargs['instance'])
post_save.connect(create_user_profile,sender=User)

@receiver(post_save, sender=User)
def save_user_profile(sender, instance, created,**kwargs):
    if created:
        instance.profile.save()

forms.py

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

class SignUpForm(UserCreationForm):
    birth_date = forms.DateField()
    location = forms.CharField()
    password1 = forms.CharField(label=("Password"), widget=forms.PasswordInput) 
    password2 = forms.CharField(label=("Confirm password"), widget=forms.PasswordInput)

    class Meta:
        model = User
        fields = ('username', 'first_name', 'last_name', 'location','email', 'birth_date')
        widgets = {
            'birth_date': forms.DateInput(attrs={'class':'datepicker'}),
        }
        labels = {
            'username': ('Capser name'),
        }
        help_texts = {
            'username' : None,
            'birth_date': None,
        }

views.py

class UserFormView(View):
    form_class = SignUpForm
    template_name = 'home/registration_form.html'

    #display a blank form
    def get(self, request):
        form = self.form_class(None)
        return render (request, self.template_name, {'form': form})

    #process form data
    def post(self, request):
        form = self.form_class(request.POST)

        if form.is_valid():
            user = form.save(commit=False)

            #user.refresh_from_db()  # load the profile instance created by the signal
            password = form.cleaned_data['password1']
            user.set_password(password)
            username = form.cleaned_data['username']
            user.profile.birth_date = form.cleaned_data.get('birth_date')
            user.profile.location = form.cleaned_data.get('location')    
            user.save()

            #return user objects if credentials are correct
            user = authenticate(username=username, password=password)

            if user is not None:
                if user.is_active:
                    login(request, user)
                    return redirect('home:home')

        return render (request, self.template_name, {'form': form})

如果我取消注释评论的lins user.refresh_from_db(),我会收到以下错误:Exception Type: DoesNotExist, Exception Value:
User matching query does not exist.

我根本不确定,但我怀疑models.py中的信号无法正常工作。

任何人都可以提供帮助吗?

2 个答案:

答案 0 :(得分:1)

首先,您无法分配:user.profile,因为user是模型User的实例,它没有此属性。

我不推荐在使用信号创建用户后用于创建配置文件的结构。您最好使用其属性(用户名,密码,电子邮件)创建用户,然后创建配置文件实例。

user.save()
Profile.objects.create(
    user=user,
    location=form.cleaned_data.get('location'),
    birth_date=form.cleaned_data.get('birth_date'))

如果您仍想使用信号执行此任务,则应搜索"如何通过信号传递参数"。因此,您可以通过字典传递location和birth_date,并使用此数据创建配置文件。

答案 1 :(得分:0)

当特定User has no profile没有相关user实例时,异常profile异常会引发异常。因此,您无法通过user.profile访问配置文件实例。因此,请确认用户是否有profile instance 因此,请将signals.py更改为以下

@receiver(post_save, sender=User)
def create_user_profile(sender, instance, created, **kwargs):
    if created:
         Profile.objects.create(user=instance,location='some location')
post_save.connect(create_user_profile,sender=User)


我不认为你需要第二个信号(save_user_profile)什么都不做(我想是这样),或者你可以将这两个信号组合在一起,因为它们来自同一个senderUser