Edit/show Primary Key in Django Admin - django

It appears Django hides fields that are flagged Primary Key from being displayed/edited in the Django admin interface.
Let's say I'd like to input data in which I may or may not want to specify a primary key. How would I go about displaying primary keys in the admin interface, and how could I make specifying it optional?

I also wanted to simply show the 'id' (primary key) within the Django admin, but not necessarily edit it. I just added it to the readonly_fields list, and it showed up fine. IE:
class StudentEnrollmentInline(admin.TabularInline):
model = Enrollment
readonly_fields=('id',)
whereas if I tried to add it to the 'fields' list, Django got upset with me, saying that field didn't exist...

If you explicitly specify the primary key field in your models (with primary_key=True), you should be able to edit it in the admin.
For Django models created via ./manage.py syncdb the following primary key field is added automatically:
id = models.AutoField(primary_key=True)
if you change (or add) that to your model explicitly as an IntegerField primary key, you'll be able to edit it directly using the admin:
id = models.IntegerField(primary_key=True)
But as others pointed out, this is a potential minefield...

To show the primary key, which by default will have a column name of "id" in the database - use "pk"
def __str__(self):
return '{} - {} ({})'.format(self.pk, self.name, self.pcode)

It doesn't make sense to have an optional primary key. Either the PK is an autoincrement, in which case there's no need to edit it, or it's manually specified, in which case it is always required.
Why do you need this?

In django documentation, there is a short sentence about that, which is not clear:
If neither fields nor fieldsets options are present, Django will default to displaying each field that isn't an AutoField and has editable=True, in a single fieldset, in the same order as the fields are defined in the model.
Reason is, django do not allow you to edit an AutoField by any means (and that is the right thing since it is an auto increment value and should not be edited). #mnelson4's answer is a good approach to display it.

The answer with the highest votes didn't work for me. I needed a getter.
class StudentEnrollmentInline(admin.TabularInline):
model = Enrollment
readonly_fields=('student_enrollment_id',)
def student_enrollment_id(self, obj):
return obj.id
Using django 1.11

Related

Confusion in id parameter in django

I was making an E Commerce website and added various products in it. Now for making a cart i made a add to cart button. And in HTML i assigned an id to this button. The id was pr{{product.id}}. I have not made buttons individually for every item. There is a for loop running which creates buttons. Now My doubt is that i have not assigned any field id in the models class. But still this code is running and when i printed the id's on the console i realised that it prints like pr32, pr33, pr34 ie in a sequential manner. So is there any product.id field predefined in django??
My doubt is that I have not assigned any field id in the models class.
You don't need to. If you do not add a primary key yourself, Django will add a field with the name id that is an AutoField. This is documented in the Automatic primary key fields section of the documentation:
By default, Django gives each model the following field:
id = models.AutoField(primary_key=True)
This is an auto-incrementing primary key.
If you’d like to specify a custom primary key, specify
primary_key=True on one of your fields. If Django sees you’ve
explicitly set Field.primary_key, it won’t add the automatic id
column.
Each model requires exactly one field to have primary_key=True
(either explicitly declared or automatically added).
So to answer your question:
So is there any product.id field predefined in django?
Yes, if you did not specify a field with primary_key=True yourself.

Does Django Class Based Views automatically assign form value for templates

I use Django 2
This is what my view.py contains
class SchoolCreateView(CreateView):
fields = ("name","principal","location")
model = models.School
The template (html file) used by this view contains the code:
form.instance.pk
And it works. It returns the correct primary key. I don't understand why.
Why does this work when I have not defined the form object in my view? Is the value of form automatically assigned when using CBVs in Django?
Follow up question. I know that form.instance represents a row in the model but what does form itself represent? My current understanding with forms is that it represents request.POST from views.py (basing my knowledge from function views). But that wouldn't make sense because the client has yet to make a POST request since he is still going to create a data entry which will be posted but is not being posted yet.
Pk is a primary key field, which is id by default. if you define other field as primary key, calling pk will return this.
From documentation:
By default, Django gives each model the following field:
id = models.AutoField(primary_key=True)
This is an auto-incrementing primary key.
If you’d like to specify a custom primary key, specify primary_key=True on one of your fields. If Django sees you’ve explicitly set Field.primary_key, it won’t add the automatic id column.
Each model requires exactly one field to have primary_key=True (either explicitly declared or automatically added).

Set admin date_hierarchy to a ForeignKey date field

When I try to set
date_hierarchy = "schedule__date"
Where schedule is a foreign key.
I get the following error.
'TestAdmin.date_hierarchy' refers to field 'schedule__date' that is missing from model 'testing.Test'.
I understand the error. What I'm hoping for is that there is some sort of workaround here to allow me to have date_hierarchy from a foreign key date field. I have tried setting a method and propery within the Test model that returns the date and setting that method/property as the date_hierarchy, but no luck.
It seems foolish to have to add another column to my table for the schedule__date when I already have it stored in another table from the foreign key.
The ability to reference fields on related models was added in Django 1.11:
Minor features
django.contrib.admin
ModelAdmin.date_hierarchy can now reference fields across relations.
https://docs.djangoproject.com/en/1.11/releases/1.11/
Unforturnately, this isn't possible with the current django. The date_hierarchy option is explicitly required to be a DateTimeField or DateField:
https://github.com/django/django/blob/stable/1.10.x/django/contrib/admin/checks.py#L837

How to get the ID of a just created record in Django?

I'm using Django 1.3 for one of my projects and I need to get the ID of a record just saved in the database.
I have something like the code below to save a record in the database:
n = MyData.objects.create(record_title=title, record_content=content)
n.save()
The ID of the record just saved auto-increments. Is there a way to get that ID and use it somewhere else in my code?
Use n.id after the save.
See "Auto-incrementing primary keys".
It would be n.pk.
To quote "Model.pk":
Regardless of whether you define a
primary key field yourself, or let
Django supply one for you, each model
will have a property called pk. It
behaves like a normal attribute on the
model, but is actually an alias for
whichever attribute is the primary key
field for the model. You can read and
set this value, just as you would for
any other attribute, and it will
update the correct field in the model.
The ID will be automatically updated in your model, so immediately after your n.save() line you can read n.id and it will be populated.
Remove save() and get pk directly:
n = MyData.objects.create(record_title=title, record_content=content)
n.pk
If someone reading this question and after check the other answers still having problems accessing the id after the creation of the object.
Be sure you don't define id as an Integer in your model. If you decide to declare it anyways, use Autofield but you don't need to, It is for free with models.Model
#No
class TestModel(models.Model):
id = models.IntegerField(primary_key=True)
something...
#Ok
class TestModel(models.Model):
id = models.AutoField(primary_key=True)
something...
#Ok
class TestModel(models.Model):
something...
if you do define id as Integer, TestModel.objects.create( or with save() will return None.
I had a similar issue with accessing the id. In Django 3.0.5, this is how I accessed the id. Using your example and variable name, see below:
instance = n.save()
# return the id
instance[0].id
The variable 'instance' above is a list. Accessing id in the methods described above returns an AttributeError ("object has no attribute 'id'") in Django 3.
This answer applies when using modelformset_factory. This is true when creating a Form class from a Django model as described in the Django docs

How to mention other field as Foreign Key in Django Model

In my model i have
book_id PK
book_number as unique field
Now in my Author model i want to set up
book_number as Foreign key not book_id
Is this possible
to_field.
ForeignKey refers to an entity by it's primary key, by database design. You should probably not do it although, you might be able to fake it within django by lieing within Model.Meta what the primary key is.
The right approach seems to me, is to make the book_number, the PK, if you are confident there aren't any repeats, and may be still retain the serial type for book_id.