为了账号安全,请及时绑定邮箱和手机立即绑定

为外键字段创建 post_save 信号

为外键字段创建 post_save 信号

慕姐4208626 2021-11-02 20:00:52
我有一个包含经验和教育作为外键领域的配置文件模型。当我访问配置文件模板时,它会抛出。我试过post_save,def create_education(sender, instance, created, **kwargs):    if created:        Profile.objects.create(education=instance)    post_save.connect(create_education, sender=CustomUser)它抛出这个错误,如何定义 post_save 信号以便在创建个人资料时创建经验和教育?注意:我仔细检查了错误是因为外部字段为空,即当我在 django admin 中添加经验和教育字段时没有错误。模型.pyclass Work_Experience(models.Model):    job_title       = models.CharField(max_length=100, null=True, blank=True)    company         = models.CharField(max_length=100, null=True, blank=True)    description     = models.CharField(max_length=300, null=True, blank=True)    exp_start_date  = models.DateField(null=True, blank=True)    exp_end_date    = models.DateField(null=True, blank=True)class Education(models.Model):    degree      = models.CharField(max_length=100, null=True, blank=True)    school      = models.CharField(max_length=100, null=True, blank=True)    edu_start_date  = models.DateField(null=True, blank=True)    edu_end_date    = models.DateField(null=True, blank=True)class Profile(models.Model):        experience    = models.ForeignKey(Work_Experience, on_delete=models.SET_NULL, null=True, blank=True)    education     = models.ForeignKey(Education, on_delete=models.SET_NULL, null=True, blank=True)
查看完整描述

2 回答

?
小唯快跑啊

TA贡献1863条经验 获得超2个赞

为什么会出错?

在行中:


self.fields['job_title'].initial = self.instance.experience.job_title

您正在处理一个Profile没有相关experience.


如何定义 post_save 信号以便在创建个人资料时创建经验和教育?

如果你想每次创建一个Profile它都会填充 amexperience并且education你应该有一个像这样的信号:


def create_profile(sender, instance, created, **kwargs):

    if created:

        experience = Work_Experience.objects.create(profile=instance)

        education = Education.objects.create(profile=instance)


post_save.connect(create_profile, sender=Profile)

为什么post_save调用save()表单的时候没有触发信号?

model = super(ProfileSettingsForm, self).save(commit=False)

根据文档:


这个 save() 方法接受一个可选的 commit 关键字参数,它接受 True 或 False。如果您使用 commit=False 调用 save(),那么它将返回一个尚未保存到数据库的对象。在这种情况下,您可以在生成的模型实例上调用 save() 。如果您想在保存对象之前对其进行自定义处理,或者您想使用专门的模型保存选项之一,这将非常有用。默认情况下,commit 为 True。


所以当你做的时候:


model.experience.job_title = jt

您的post_save信号尚未触发,因此model.experience仍然存在None错误:


'NoneType' 对象没有属性 job_title。


查看完整回答
反对 回复 2021-11-02
?
阿晨1998

TA贡献2037条经验 获得超6个赞

你不能那样做,我建议你阅读 django 文档。只需这样做: 在此处更新


下面的代码按预期工作..


from django.conf import settings

from django.db.models.signals import post_save

from django.dispatch import receiver

from django.contrib.auth.base_user import AbstractBaseUser

from latiro_app.managers import UserManager




class User(AbstractBaseUser):

     email         = models.CharField(verbose_name='email or phone number ', max_length=50, unique=True )

     first_name    = models.CharField('first name', max_length=15,blank=True)

     last_name     = models.CharField('last name', max_length=15,blank=True)

     country       = CountryField(blank=True)

     date_joined   = models.DateTimeField('date joined', auto_now_add=True)

     slug          = models.SlugField('slug', max_length=50, unique=True, null=True) 

     is_active     = models.BooleanField('active',default=False)

     is_staff      = models.BooleanField('staff', default=False)

     email_confirmed = models.BooleanField(default=False)



     objects = UserManager()


     USERNAME_FIELD = 'email'

     REQUIRED_FIELDS = []



     class Meta:

         db_table = "users" 

         permissions = (

            ("edit_user", "Edit User"),

            )









class WorkExperience(models.Model):

     job_title       = models.CharField(max_length=100, null=True, blank=True)

     company         = models.CharField(max_length=100, null=True, blank=True)

     description     = models.CharField(max_length=300, null=True, blank=True)

     exp_start_date  = models.DateField(null=True, blank=True)

     exp_end_date    = models.DateField(null=True, blank=True)


    class Meta:

         db_table = "experience"


    def __str__(self):

        return (self.job_title)



class Education(models.Model):

    degree      = models.CharField(max_length=100, null=True, blank=True)

    school      = models.CharField(max_length=100, null=True, blank=True)

    edu_start_date  = models.DateField(null=True, blank=True)

    edu_end_date    = models.DateField(null=True, blank=True)


    class Meta:

        db_table = "education"


    def __str__(self):

        return (self.degree)





class Profile (models.Model):

    user            = models.OneToOneField(settings.AUTH_USER_MODEL, on_delete= models.CASCADE,

                                     verbose_name='list of users', null=True)

    experience    = models.ForeignKey(WorkExperience, on_delete=models.SET_NULL, null=True, blank=True)

    education     = models.ForeignKey(Education, on_delete=models.SET_NULL, null=True, blank=True)





    def __str__(self):

        return (self.user)


    class Meta:

        db_table = "profile"


@receiver(post_save, sender=settings.AUTH_USER_MODEL)

def create_profile(sender, instance, created, **kwargs):

    if created and not kwargs.get('raw', False):

        profile = Profile(user=instance)

        profile.save()

这应该有效。在我的数据库上测试:


+----+--------------+---------------+---------+

| id | education_id | experience_id | user_id |

+----+--------------+---------------+---------+

|  1 |         NULL |          NULL |       2 |

+----+--------------+---------------+---------+

更新配置文件时,user_id 实例将更新education_id 和experience_id 上的空值。


现在用户可以像这样更新他/她的个人资料: 注意:我没有使用信号。


#Form.py 

class EducationForm(forms.ModelForm):

    degree         = forms.CharField(max_length=40, required=False)

    school         = forms.CharField(max_length=40, required=False)

    edu_start_date = forms.DateField(required=False, 

                     input_formats=settings.DATE_INPUT_FORMATS)

    edu_end_date   = forms.DateField(required=False, 

    input_formats=settings.DATE_INPUT_FORMATS)



    class Meta:

        model= Education

        fields =["degree","school", "edu_start_date","edu_start_date"]


#View.py 

class EducationFormView(UpdateView):

    model = Education

    form_class = EducationForm

    template_name = 'latiro_app/education_form.html'


    def get_success_url(self):

        return reverse_lazy('users:profile_settings',

                                            args =(self.object.id,))


    def get(self, form, ** kwargs):

       profile_instance = get_object_or_404(self.model, user_id=self.kwargs['pk'])

        #Pass user profile data to the form 

        context = {'form':self.form_class(instance=profile_instance)}

        if self.request.is_ajax():

            kwargs['ajax_form'] = render_to_string(self.template_name, context, request=self.request )

            return JsonResponse(kwargs)

        else:

            return render(self.request, self.template_name, context)


查看完整回答
反对 回复 2021-11-02
  • 2 回答
  • 0 关注
  • 252 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信