11

I have an overrided User model and a Cart model. I expect that a Cart model instance is created automatically once a User model instance is created. I am trying to pass the newly registered user into the get_queryset method, but no idea how to do it. Are there any other better ways of doing this? It's because I may need to do the same thing for other models unlike the User model which has a form that can pass values to the get_queryset method.

account/models.py:

class Cart(models.Model):

    user = models.OneToOneField(User, on_delete=models.CASCADE, null=True)

    def __str__(self):
        return self.user.email + '_cart'

account/views.py:

class RegisterView(generic.CreateView):
    template_name = 'account/register.html'
    form_class = RegisterForm
    success_url = reverse_lazy('book:home')

    def get_queryset(self):
        sign_up = self.request.POST.get('register')
        if sign_up:
            c = Cart.objects.create(user=???)
            c.save()

account/templates/account/register.html:

<form name="register" method="post">{% csrf_token %}
    {{ form.as_p }}
    <input type="submit" value="Sign Up">
</form>

4 Answers 4

23

Method-1: Use Django's post_save signal (as @AKX said)

from django.contrib.auth import get_user_model


@receiver(post_save, sender=get_user_model())
def create_user_cart(sender, instance, created, **kwargs):
    if created:
        Cart.objects.create(user=instance)


Method-2: Override the save() method of your User model or extended Usermodel

class MyUserModel(....):
    # your code
    def save(self,*args,**kwargs):
        created = not self.pk
        super().save(*args,**kwargs)
        if created:
            Cart.objects.create(user=self)
Sign up to request clarification or add additional context in comments.

3 Comments

Hello @JPG, i would like to know what is this created = not self.pk doing! i am little bit confused in here, this method worked for me but i would like to know how is this code actually working!
@LuisRodriguez self.pk will be None for instances that are going to be created.
@LuisRodriguez pk is Django's reliable shortcut for the primary key field. Basically what the code is doing checking if the primary key was set before save, if so this is a new object creation, otherwise it is an update.
8

Use a Django post_save signal hooked up to the User model.

See the signals tutorial for more information.

Comments

2

override save method, signals are harder to read/track through multiple files and are synchronous.

https://lincolnloop.com/blog/django-anti-patterns-signals/

class Pizza(models.Model):
    has_pepperoni = models.BooleanField(default=False)

    def save(self, *args, **kwargs):
        created = self.pk is None
        super(Pizza, self).save(*args, **kwargs)
        if created and self.has_pepperoni:
            ToppingSales.objects.filter(name='pepperoni').update(
                units_sold=F('units_sold') + 1)           


class ToppingSales(models.Model):
    name = models.CharField(max_length=100, unique=True)
    units_sold = models.PositiveIntegerField(default=0)

Comments

0

I believe the modern ways (as per the docs) are to do this during a create() class method or to write a custom manager.

https://docs.djangoproject.com/en/3.1/ref/models/instances/

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.