Boky
Boky

Reputation: 12064

Saving to database with one query

I have standard django User model and I have an extended model Member. The Member model is connected to Subscription model.

class Type(models.Model):
    limit = models.IntegerField()
    name = models.CharField(max_length=50)
    default = models.BooleanField()

    def __str__(self):
        return self.name


class Subscription(models.Model):
    started = models.DateField()
    type = models.OneToOneField(Type)

    def __str__(self):
        return self.type.name


class Member(models.Model):
    user = models.ForeignKey(to=User)
    number = models.CharField(max_length=10)
    match_code = models.CharField(max_length=50)
    parent = models.ForeignKey("self", null=True, blank=True)
    name = models.CharField(max_length=100)
    address = models.CharField(max_length=255)
    postcode = models.CharField(max_length=10)
    city = models.CharField(max_length=100)
    country = models.ForeignKey(to=Country, null=True)
    language = models.ForeignKey(to=Language)
    telephone = models.CharField(max_length=50)
    mobile = models.CharField(max_length=50)
    main_email = models.EmailField(null=True, blank=True)
    active = models.BooleanField()
    subscription = models.ForeignKey(Subscription)

    def __str__(self):
        return self.name

When I create a new user, and when I want to save it to database I do it as follows :

    language = Language.objects.get(key="EN")
    country = Country.objects.get(key="BE")

    # Add to user model
    user = User()
    user.username = request.POST['email']
    user.first_name = request.POST['firstname']
    user.last_name = request.POST['lastname']
    user.email = request.POST['email']
    user.set_password(request.POST['password'])
    user.save()

    # Add subscription
    subscription = Subscription()
    subscription.started = datetime.date.today()
    subscription.type = Type.objects.filter(default=True)
    last_subscription = Subscription.objects.all().order_by('-id')[0]

    # Get the last field from user model
    last_user = User.objects.all().order_by('-id')[0]
    # Add to member model with the last user
    member = Member()
    member.number = request.POST['member_id']
    member.address = request.POST['address']
    member.postcode = request.POST['postcode']
    member.city = request.POST['city']
    member.country = country
    member.telephone = request.POST['telephone']
    member.mobile = request.POST['mobile']
    member.user = last_user
    member.language = language
    member.active = False
    member.subscription = last_subscription
    member.save()

But I think that I hit the database to many times. Is there any better solution to do it? Can it be done maybe with one query?

Upvotes: 1

Views: 57

Answers (2)

e4c5
e4c5

Reputation: 53734

Several things wrong here

subscription.type = Type.objects.filter(default=True)

You are asigning a whole queryset to subscription.type this code would produce an error here. Secondly don't use default as a model field name.

last_subscription = Subscription.objects.all().order_by('-id')[0]

Not quite sure what you are trying to do here. The efficient and error free approach would be to save the subscription object and use it's generated id for your next operation.

user.username = request.POST['email']
user.first_name = request.POST['firstname']
user.last_name = request.POST['lastname']
user.email = request.POST['email']
user.set_password(request.POST['password'])

It's not a good idea to directly pass in post data to models. You should use django forms to validate them first.

last_user = User.objects.all().order_by('-id')[0]
# Add to member model with the last user

This may or may not be the user that you just saved. It's very likely that another instance would have saved another user just after this thread did. It's safer to use user.id (as already mentioned regarding subscription)

Upvotes: 3

Andrew Sklyarov
Andrew Sklyarov

Reputation: 75

Actually, you don't need to get last subscription or last user instance. You can(and should!) just use your subscription and user objects. Because they will have id after the save method will be called."Auto-incrementing primary keys"

Also, it seems that you've never saved the subscription instance.

Upvotes: 1

Related Questions