views:

71

answers:

3

[Update: Changed question title to be more specific]

Sorry if I didn't make the question very well, I can't figure how to do this:

class WhatEver():
    number = model.IntegerField('Just a Field', default=callablefunction)
...

Where callablefunction does this query:

from myproject.app.models import WhatEver

def callablefunction():
    no = WhatEver.objects.count()
    return no + 1

I want to automatically write the next number, and I don't know how to do it.

I have errors from callablefunction stating that it cannot import the model, and I think there must be an easier way to do this. There's no need even to use this, but I can't figure how to do it with the pk number.

I've googled about this and the only thing I found was to use the save() method for auto incrementing the number... but I wanted to show it in the <textfield> before saving...

What would you do?

A: 

Every Django model already has an auto-generated primary key:

id = models.AutoField(primary_key=True)

It seems you are trying to duplicate an already existing behavior, just use the object primary key.

Yuval A
I know about primary keys, but I have to show that number inside the django admin page. Is there any way to do that?
Oscar Carballal
See http://stackoverflow.com/questions/2531762/edit-show-primary-key-in-django-admin
Yuval A
That does not work. If you put it as an AutoField django crashes. And if its an IntegerField it does not work as expected. It just becomes a normal IntegerField. I need that field to be auto filled with the next number (I think i'm very bad explaining myself)
Oscar Carballal
If you must, just add another field which is an `AutoField`, but not a primary key. In any case, sounds like you're doing something wrong.
Yuval A
A: 

You have errors in code, that's why you can't import it:

from django.db import models
class WhatEver(models.Model):
    number = models.IntegerField('Just a Field', default=0)

and Yuval A is right about auto-incrementing: you don't even need to declare such a field. Just use the pk or id, they mean the same unless there's a composite pk in the model:

> w = Whatever(number=10)
> w
<Whatever object>
> w.id
None
> w.save()
> w.id
1

[update] Well, I haven't tried a callable as a default. I think if you fix these errors, it must work.

culebrón
I think as for django 1.2.1 Field.default() can have a callable object, instead of just a number/string
Oscar Carballal
A: 

Got it! I hope this will help everyone that has any problems making a auto-filled and auto-incrementing field in django. The solution is this, I'll put my code:

class Cliente(models.Model):
    """This is the client data model, it holds all client information. This
       docstring has to be improved."""
    def number():
        no = Cliente.objects.count()
        if no == None:
            return 1
        else:
            return no + 1

    clientcode = models.IntegerField(_('Code'), max_length=6, unique=True, \
    default=number)

    [... here goes the rest of your model ...]

Take in care:

  • The number function doesn't take any arguments (not even self)
  • It's written BEFORE everything in the model
  • This was tested on django 1.2.1

This function will automatically fill the clientcode field with the next number (p.e. If you have 132 clients, when you add the next one the field will be filled with clientcode number 133)

I know that this is absurd for most of the practical situations, since the PK number is also auto-incrementing, but there's no way to autofill or take a practical use for it inside the django admin.

[update: as I stated in my comment, there's a way to use the primary key for this, but it will not fill the field before saving]

Oscar Carballal
Are you sure this code will also work with concurrent transactions? What happens when two requests both do a `count()` at the same time, and write the same value later?
vdboor
That's true... in my use case it doesn't matter because there will never be two requests at a time... but even then I must think a better way to implement this. Thanks for the advice! :)
Oscar Carballal
I've been able to perform something similar to what I want making this field: `id=models.IntegerField(primary_key=True, blank=True)` The only thing is that it's not auto filled, but solves the problem of simultaneous requests (I think)
Oscar Carballal