Search code examples
pythondjangodjango-viewsdjango-formssignals

Automatically updating a model field when it is created


I would like to automatically update a model field when it is created. So this is my situation. I have a custom User model that my customer can use to login. After they login, they will go to the account/profile page, which has a link to a form. Currently, when the user submits the form, it creates an instance of the LevelTest model(which is something I just need for the website to work). Here is the view class for the form:

class LevelTestView(generic.CreateView):
    template_name = "leads/leveltest.html"
    form_class = LevelTestModelForm

    def get_success_url(self):
        return reverse("profile-page")

and here is the LevelTestModelForm:

class LevelTestModelForm(forms.ModelForm):
    class Meta:
        model = LevelTest
        fields = (
            'first_name',
            'last_name',
            'age',
            'username',
        )

What I want to fill in automatically is the username field. In fact, I wish it doesn't even show up on the form itself when the user types in. The username is a field in the User Model, so I just want the new LevelTest's username field filled in with the current user's username. Hence, I used a post_save signal like below(which doesn't work):

def post_leveltest_created_signal(sender, instance, created, **kwargs):
    if created:
        instance.objects.update(
            username=instance.user.username,
            description='Add Description',
            phone_number=instance.user.cellphone,
            email=instance.user.username,
        )

    
post_save.connect(post_leveltest_created_signal, sender=LevelTest)

I hope you guys could help me tweek the post_save signal, so that when the user creates a LevelTest instance, the LevelTest's username field(as well as the phone_number and email) is filled in with the user model's information. Thanks a lot!


Solution

  • If I understand you correct, you don't need to use signals, you can save username easier:

    Extend get_form_kwargs method in your CreateView, like that:

     class LevelTestView:(generic.CreateView)
         ...
         def get_form_kwargs(self):
             kwargs = super().get_form_kwargs()
             kwargs['user'] = self.request.user
             return kwargs
    

    Extend __init__ and save method in your Form, like that:

    class LevelTestModelForm(forms.ModelForm):
        ...
        def __init__(self, user, *args, **kwargs):
            self.user = user
            super().__init__(*args, **kwargs)
        ...
        def save(self, commit=True):
            leveltest = super().save(commit=False)
            # I think it would be better if you saved only 'user' instance
            # like this - leveltest.user = self.user (of course if you have fk to user model)
            leveltest.username = self.user.username
            leveltest.phone_number=self.user.cellphone
            leveltest.email=self.user.username
            leveltest.save()
            return leveltest