{"id":75643,"date":"2020-01-20T11:24:53","date_gmt":"2020-01-20T05:54:53","guid":{"rendered":"https:\/\/www.vskills.in\/certification\/tutorial\/?p=75643"},"modified":"2024-04-12T14:17:14","modified_gmt":"2024-04-12T08:47:14","slug":"using-the-admin-interface","status":"publish","type":"page","link":"https:\/\/www.vskills.in\/certification\/tutorial\/using-the-admin-interface\/","title":{"rendered":"Using the Admin Interface"},"content":{"rendered":"<p>When you ran django-admin startproject mysite, Django created and configured the default admin site for you. All that you need to do is create an admin user (superuser) and then you can log into the admin site.<\/p>\n<p>If you are using Visual Studio, you don\u2019t need to complete this next step at the command line, you can just add a super user from the \u201cProject\u201d menu tab within Visual Studio. To create an admin user, run the following command from within your project virtual environment:<\/p>\n<ul>\n<li>(env_mysite) C:\\&#8230;\\mysite_project\\mysite&gt; python manage.py createsuperuser<\/li>\n<li>Enter your desired username and press enter.<\/li>\n<li>Username: admin<\/li>\n<li>You will then be prompted for your desired email address:<\/li>\n<li>Email address: admin@example.com<\/li>\n<li>The final step is to enter your password. You will be asked to enter your password twice, the second time as a confirmation of the first. Note that you will have to come up with a reasonable secure password, even for testing.<\/li>\n<\/ul>\n<p>Django automatically checks the strength of your password and won\u2019t let you use a simple or common password. This can be a little annoying when you\u2019re testing, but at least you can be confident that Django won\u2019t let you break it\u2019s carefully crafted security with a dumb password.<\/p>\n<pre>Password: **********\nPassword (again): *********\nSuperuser created successfully.<\/pre>\n<h3>Start the Development Server<\/h3>\n<p>In Django 1.11, the django admin site is activated by default. Let\u2019s start the development server and explore it. Start the development server like so:<\/p>\n<p>(env_mysite) C:\\&#8230;\\mysite_project\\mysite&gt; python manage.py runserver<br>\nNow, open a web browser and go to \/admin\/ on your local domain \u2013 e.g., http:\/\/127.0.0.1:8000\/admin\/. You should see the admin\u2019s login screen.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter wp-image-128577 size-full\" src=\"https:\/\/www.vskills.in\/lms\/wp-content\/uploads\/2016\/07\/8.png\" alt=\"\" width=\"828\" height=\"625\"><\/p>\n<p>Since translation is turned on by default, the login screen may be displayed in your own language, depending on your browser\u2019s settings and on whether Django has a translation for this language.<\/p>\n<h3>Enter the Admin Site<\/h3>\n<p>Now, try logging in with the superuser account you created in the previous step. You should see the Django admin index page. You should see two types of editable content: Groups and Users. They are provided by django.contrib.auth, the authentication framework shipped by Django. The admin site is designed to be used by nontechnical users, and as such it should be pretty self-explanatory. Nevertheless, I\u2019ll give you a quick walk-through of the basic features.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter wp-image-128578 size-full\" src=\"https:\/\/www.vskills.in\/lms\/wp-content\/uploads\/2016\/07\/9.jpg\" alt=\"\" width=\"1105\" height=\"765\"><\/p>\n<p>Each type of data in the Django admin site has a change list and an edit form. Change lists show you all the available objects in the database, and edit forms let you add, change or delete particular records in your database. Click the \u201cChange\u201d link in the \u201cUsers\u201d row to load the change list page for users.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter wp-image-128579 size-full\" src=\"https:\/\/www.vskills.in\/lms\/wp-content\/uploads\/2016\/07\/10.jpg\" alt=\"\" width=\"1124\" height=\"768\"><\/p>\n<p>This page displays all users in the database; you can think of it as a prettied-up web version of a SELECT * FROM auth_user; SQL query. If you\u2019re following along with our ongoing example, you\u2019ll only see one user here, but once you have more users, you\u2019ll probably find the filtering, sorting and searching options useful.<\/p>\n<p>Filtering options are at right, sorting is available by clicking a column header, and the search box at the top lets you search by username. Click the username of the user you created, and you\u2019ll see the edit form for that user (Figure 5-4). This page lets you change the attributes of the user, like the first\/last names and various permissions.<\/p>\n<p>Note that the user\u2019s password in not shown. As a security measure, Django doesn\u2019t store raw passwords, so there is no way to retrieve a password, you have to change it.<\/p>\n<p>Another thing to note here is that fields of different types get different widgets \u2013 for example, date\/time fields have calendar controls, Boolean fields have checkboxes, character fields have simple text input fields.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter wp-image-128580 size-full\" src=\"https:\/\/www.vskills.in\/lms\/wp-content\/uploads\/2016\/07\/11.jpg\" alt=\"\" width=\"1124\" height=\"768\"><\/p>\n<p>You can delete a record by clicking the delete button at the bottom left of its edit form. That\u2019ll take you to a confirmation page, which, in some cases, will display any dependent objects that will be deleted, too. (For example, if you delete a publisher, any book with that publisher will be deleted, too!)<\/p>\n<p>You can add a record by clicking \u201cAdd\u201d in the appropriate column of the admin home page. This will give you an empty version of the edit page, ready for you to fill out. You\u2019ll also notice that the admin interface handles input validation for you. Try leaving a required field blank or putting an invalid date into a date field, and you\u2019ll see those errors when you try to save, as shown below.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter wp-image-128581 size-full\" src=\"https:\/\/www.vskills.in\/lms\/wp-content\/uploads\/2016\/07\/12.jpg\" alt=\"\" width=\"1124\" height=\"912\"><\/p>\n<p>When you edit an existing object, you\u2019ll notice a History link in the upper-right corner of the window. Every change made through the admin interface is logged, and you can examine this log by clicking the History link.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter wp-image-128582 size-full\" src=\"https:\/\/www.vskills.in\/lms\/wp-content\/uploads\/2016\/07\/13.jpg\" alt=\"\" width=\"1139\" height=\"504\"><\/p>\n<h3>How the Admin Site Works<\/h3>\n<p>Behind the scenes, how does the admin site work?<\/p>\n<p>It\u2019s pretty straightforward. When Django loads at server startup, it runs the admin.autodiscover() function. In earlier versions of Django, you used to call this function from urls.py, but now Django runs it automatically. This function iterates over your INSTALLED_APPS setting and looks for a file called admin.py in each installed app. If an admin.py exists in a given app, it executes the code in that file.<\/p>\n<p>The admin site will only display an edit\/change interface for models that have been explicitly registered with admin.site.register() entered into the app\u2019s admin.py file. This is why your books model is not displaying yet \u2013 we have not registered the model with the admin. We will get to that next.<\/p>\n<p>The app django.contrib.auth includes its own admin.py, which is why Users and Groups showed up automatically in the admin. Other django.contrib apps, such as django.contrib.redirects, also add themselves to the admin, as do many third-party Django applications you might download from the web.<\/p>\n<p>Beyond that, the Django admin site is just a Django application, with its own models, templates, views and URLpatterns. You add it to your application by hooking it into your URLconf, just as you hook in your own views. You can inspect its templates, views and URLpatterns by poking around in django\/contrib\/admin in your copy of the Django codebase \u2013 but don\u2019t be tempted to change anything directly in there, as there are plenty of hooks for you to customize the way the admin site works.<\/p>\n<h3>Adding Models to Django Admin<\/h3>\n<p>There\u2019s one crucial part we haven\u2019t done yet. Let\u2019s add our own models to the admin site, so we can add, change and delete objects in our custom database tables using this nice interface. We\u2019ll continue the books example, where we defined three models: Publisher, Author and Book. Within the books directory (mysite_project\\mysite\\books), startapp should have created a file called admin.py, if not, simply create one yourself and type in the following lines of code:<\/p>\n<pre>from django.contrib import admin\nfrom .models import Publisher, Author, Book\n\nadmin.site.register(Publisher)\nadmin.site.register(Author)\nadmin.site.register(Book)\n\nThis code tells the Django admin site to offer an interface for each of these models. Once you\u2019ve done this, go to your admin home page in your web browser (http:\/\/127.0.0.1:8000\/admin\/), and you should see a \u201cBooks\u201d section with links for Authors, Books and Publishers. You might have to stop and start the development server for the changes to take effect.<\/pre>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter wp-image-128583 \" src=\"https:\/\/www.vskills.in\/lms\/wp-content\/uploads\/2016\/07\/14.jpg\" alt=\"\" width=\"729\" height=\"427\"><\/p>\n<p>You now have a fully functional admin interface for each of those three models. That was easy!<\/p>\n<p>Take some time to add and change records, to populate your database with some data. If you followed examples of creating Publisher objects (and you didn\u2019t delete them), you\u2019ll already see those records on the publisher change list page.<\/p>\n<p>One feature worth mentioning here is the admin site\u2019s handling of foreign keys and many-to-many relationships, both of which appear in the Book model. As a reminder, here\u2019s what the Book model looks like:<\/p>\n<pre>class Book(models.Model):\ntitle = models.CharField(max_length=100)\nauthors = models.ManyToManyField(Author)\npublisher = models.ForeignKey(Publisher)\npublication_date = models.DateField()\n\ndef __str__(self):\nreturn self.title<\/pre>\n<p>On the Django admin site\u2019s \u201cAdd book\u201d page (http:\/\/127.0.0.1:8000\/admin\/books\/book\/add\/), the publisher (a ForeignKey) is represented by a select box, and the authors field (a ManyToManyField) is represented by a multiple-select box. Both fields sit next to a green plus sign icon that lets you add related records of that type.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter wp-image-128584 size-large\" src=\"https:\/\/www.vskills.in\/lms\/wp-content\/uploads\/2016\/07\/15-1024x763.jpg\" alt=\"\" width=\"1024\" height=\"763\"><br>\nFor example, if you click the green plus sign next to the \u201cPublisher\u201d field, you\u2019ll get a pop-up window that lets you add a publisher. After you successfully create the publisher in the pop-up, the \u201cAdd book\u201d form will be updated with the newly created publisher. Slick.<\/p>\n<p><strong>Making Fields Optional<\/strong> &#8211; After you play around with the admin site for a while, you\u2019ll probably notice a limitation \u2013 the edit forms require every field to be filled out, whereas in many cases you\u2019d want certain fields to be optional. Let\u2019s say, for example, that we want our Author model\u2019s email field to be optional \u2013 that is, a blank string should be allowed. In the real world, you might not have an e-mail address on file for every author.<\/p>\n<p>To specify that the email field is optional, edit the Author model (which, as you\u2019ll recall lives in mysite\/books\/models.py). Simply add blank=True to the email field, like so:<\/p>\n<pre>class Author(models.Model):\nfirst_name = models.CharField(max_length=30)\nlast_name = models.CharField(max_length=40)\nemail = models.EmailField(blank=True)<\/pre>\n<p>This tells Django that a blank value is indeed allowed for authors\u2019 e-mail addresses. By default, all fields have blank=False, which means blank values are not allowed.<\/p>\n<p>There\u2019s something interesting happening here. Until now, with the exception of the __str__() method, our models have served as definitions of our database tables \u2013 Pythonic expressions of SQL CREATE TABLE statements, essentially. In adding blank=True, we have begun expanding our model beyond a simple definition of what the database table looks like.<br>\nNow, our model class is starting to become a richer collection of knowledge about what Author<br>\nobjects are and what they can do. Not only is the email field represented by a VARCHAR<br>\ncolumn in the database; it\u2019s also an optional field in contexts such as the Django admin site.<\/p>\n<p>Once you\u2019ve added that blank=True, reload the \u201cAdd author\u201d edit form (http:\/\/127.0.0.1:8000\/admin\/books\/author\/add\/), and you\u2019ll notice the field\u2019s label \u2013 \u201cEmail\u201d \u2013 is no longer bolded. This signifies it\u2019s not a required field. You can now add authors without needing to provide e-mail addresses; you won\u2019t get the loud red \u201cThis field is required\u201d message anymore, if the field is submitted empty.<\/p>\n<p><strong>Making Date and Numeric Fields Optional<\/strong> &#8211; A common gotcha related to blank=True has to do with date and numeric fields, but it requires a fair amount of background explanation. SQL has its own way of specifying blank values \u2013 a special value called NULL. NULL could mean \u201cunknown,\u201d or \u201cinvalid,\u201d or some other application-specific meaning. In SQL, a value of NULL is different than an empty string, just as the special Python object None is different than an empty Python string (&#8220;&#8221;).<\/p>\n<p>This means it\u2019s possible for a particular character field (e.g., a VARCHAR column) to contain both NULL values and empty string values. This can cause unwanted ambiguity and confusion: \u201cWhy does this record have a NULL but this other one has an empty string? Is there a difference, or was the data just entered inconsistently?\u201d And: \u201cHow do I get all the records that have a blank value \u2013 should I look for both NULL records and empty strings, or do I only select the ones with empty strings?\u201d<\/p>\n<p>To help avoid such ambiguity, Django\u2019s automatically generated CREATE TABLE statements add an explicit NOT NULL to each column definition. For example, here\u2019s the generated statement for our Author model:<\/p>\n<pre>CREATE TABLE \"books_author\" (\n\"id\" serial NOT NULL PRIMARY KEY,\n\"first_name\" varchar(30) NOT NULL,\n\"last_name\" varchar(40) NOT NULL,\n\"email\" varchar(75) NOT NULL\n);<\/pre>\n<p>In most cases, this default behavior is optimal for your application and will save you from data-inconsistency headaches. And it works nicely with the rest of Django, such as the Django admin site, which inserts an empty string (not a NULL value) when you leave a character field blank.<\/p>\n<p>But there\u2019s an exception with database column types that do not accept empty strings as valid values \u2013 such as dates, times and numbers. If you try to insert an empty string into a date or integer column, you\u2019ll likely get a database error, depending on which database you\u2019re using. (PostgreSQL, which is strict, will raise an exception here; MySQL might accept it or might not, depending on the version you\u2019re using, the time of day and the phase of the moon.)<\/p>\n<p>In this case, NULL is the only way to specify an empty value. In Django models, you specify that NULL is allowed by adding null=True to a field. So that\u2019s a long way of saying this \u2013 if you want to allow blank values in a date field (e.g., DateField, TimeField, DateTimeField) or numeric field (e.g., IntegerField, DecimalField, FloatField), you\u2019ll need to use both null=True and blank=True.<\/p>\n<p>For example, let\u2019s change our Book model to allow a blank publication_date. Here\u2019s the revised code:<\/p>\n<pre>class Book(models.Model):\ntitle = models.CharField(max_length=100)\nauthors = models.ManyToManyField(Author)\npublisher = models.ForeignKey(Publisher)\npublication_date = models.DateField(blank=True, null=True)<\/pre>\n<p>Adding null=True is more complicated than adding blank=True, because null=True changes the semantics of the database \u2013 that is, it changes the CREATE TABLE statement to remove the NOT NULL from the publication_date field. To complete this change, we\u2019ll need to update the database.<\/p>\n<p>For a number of reasons, Django does not attempt to automate changes to database schemas, so it\u2019s your own responsibility to execute the python manage.py migrate command whenever you make such a change to a model. Bringing this back to the admin site, now the \u201cAdd book\u201d edit form should allow for empty publication date values.<\/p>\n<p><strong>Customizing Field Labels<\/strong> &#8211; On the admin site\u2019s edit forms, each field\u2019s label is generated from its model field name. The algorithm is simple \u2013 Django just replaces underscores with spaces and capitalizes the first character, so, for example, the Book model\u2019s publication_date field has the label \u201cPublication date.\u201d<\/p>\n<p>However, field names don\u2019t always lend themselves to nice admin field labels, so in some cases you might want to customize a label. You can do this by specifying verbose_name in the appropriate model field. For example, here\u2019s how we can change the label of the Author.email field to \u201ce-mail,\u201d with a hyphen:<\/p>\n<pre>class Author(models.Model):\nfirst_name = models.CharField(max_length=30)\nlast_name = models.CharField(max_length=40)\nemail = models.EmailField(blank=True, verbose_name ='e-mail')<\/pre>\n<p>Make that change and reload the server, and you should see the field\u2019s new label on the author edit form. Note that you shouldn\u2019t capitalize the first letter of a verbose_name unless it should always be capitalized (e.g., &#8220;USA state&#8221;). Django will automatically capitalize it when it needs to, and it will use the exact verbose_name value in other places that don\u2019t require capitalization.<\/p>\n<p><strong>Custom ModelAdmin classes<\/strong> &#8211; The changes we\u2019ve made so far \u2013 blank=True, null=True and verbose_name \u2013 are really model-level changes, not admin-level changes. That is, these changes are a fundamental part of the model and just so happen to be used by the admin site; there\u2019s nothing admin-specific about them.<\/p>\n<p>Beyond these, the Django admin site offers a wealth of options that let you customize how the admin site works for a particular model. Such options live in ModelAdmin classes, which are classes that contain configuration for a specific model in a specific admin site instance.<\/p>\n<h3>Customizing Change Lists and Forms<\/h3>\n<p>Let\u2019s dive into admin customization by specifying the fields that are displayed on the change list for our Author model. By default, the change list displays the result of __str__() for each object. Earlier, we defined the __str__() method for Author objects to display the first name and last name together:<\/p>\n<pre>class Author(models.Model):\nfirst_name = models.CharField(max_length=30)\nlast_name = models.CharField(max_length=40)\nemail = models.EmailField(blank=True, verbose_name ='e-mail')\n\ndef __str__(self):\nreturn u'%s %s' % (self.first_name, self.last_name)<\/pre>\n<p>As a result, the change list for Author objects displays each other\u2019s first name and last name together, as you can see in figure.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter wp-image-128585 size-full\" src=\"https:\/\/www.vskills.in\/lms\/wp-content\/uploads\/2016\/07\/16.jpg\" alt=\"\" width=\"1157\" height=\"640\"><\/p>\n<p>We can improve on this default behavior by adding a few other fields to the change list display. It\u2019d be handy, for example, to see each author\u2019s e-mail address in this list, and it\u2019d be nice to be able to sort by first and last name.<\/p>\n<p>To make this happen, we\u2019ll define a ModelAdmin class for the Author model. This class is the key to customizing the admin, and one of the most basic things it lets you do is specify the list of fields to display on change list pages. Edit admin.py to make these changes:<\/p>\n<pre>from django.contrib import admin\nfrom .models import Publisher, Author, Book\n\nclass AuthorAdmin(admin.ModelAdmin):\nlist_display = ('first_name', 'last_name', 'email')\n\nadmin.site.register(Publisher)\nadmin.site.register(Author, AuthorAdmin)\nadmin.site.register(Book)<\/pre>\n<p>Here\u2019s what we\u2019ve done:<br>\n\uf0fc We created the class AuthorAdmin. This class, which subclasses django.contrib.admin.ModelAdmin, holds custom configuration for a specific admin model. We\u2019ve only specified one customization \u2013 list_display, which is set to a tuple of field names to display on the change list page. These field names must exist in the model, of course.<br>\n\uf0fc We altered the admin.site.register() call to add AuthorAdmin after Author. You can read this as: \u201cRegister the Author model with the AuthorAdmin options.\u201dThe admin.site.register() function takes a ModelAdmin subclass as an optional second argument. If you don\u2019t specify a second argument (as is the case for Publisher and Book), Django will use the default admin options for that model.<\/p>\n<p>With that tweak made, reload the author change list page, and you\u2019ll see it\u2019s now displaying three columns \u2013 the first name, last name and e-mail address. In addition, each of those columns is sortable by clicking on the column header.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter wp-image-128586 size-full\" src=\"https:\/\/www.vskills.in\/lms\/wp-content\/uploads\/2016\/07\/18.jpg\" alt=\"\" width=\"1157\" height=\"640\"><\/p>\n<p>Next, let\u2019s add a simple search bar. Add search_fields to the AuthorAdmin, like so:<\/p>\n<pre>class AuthorAdmin(admin.ModelAdmin):\nlist_display = ('first_name', 'last_name', 'email')\nsearch_fields = ('first_name', 'last_name')<\/pre>\n<p>Reload the page in your browser, and you should see a search bar at the top. We\u2019ve just told the admin change list page to include a search bar that searches against the first_name and last_name fields. As a user might expect, this is case-insensitive and searches both fields, so searching for the string \u201cbar\u201d would find both an author with the first name Barney and an author with the last name Hobarson.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter wp-image-128586 size-full\" src=\"https:\/\/www.vskills.in\/lms\/wp-content\/uploads\/2016\/07\/18.jpg\" alt=\"\" width=\"1157\" height=\"640\"><\/p>\n<p>&nbsp;<\/p>\n<p>Next, let\u2019s add some date filters to our Book model\u2019s change list page:<\/p>\n<pre>from django.contrib import admin\nfrom .models import Publisher, Author, Book\n\nclass AuthorAdmin(admin.ModelAdmin):\nlist_display = ('first_name', 'last_name', 'email')\nsearch_fields = ('first_name', 'last_name')\n\nclass BookAdmin(admin.ModelAdmin):\nlist_display = ('title', 'publisher', 'publication_date')\nlist_filter = ('publication_date',)\n\nadmin.site.register(Publisher)\nadmin.site.register(Author, AuthorAdmin)\nadmin.site.register(Book, BookAdmin)<\/pre>\n<p>Here, because we\u2019re dealing with a different set of options, we created a separate ModelAdmin class \u2013 BookAdmin. First, we defined a list_display just to make the change list look a bit nicer. Then, we used list_filter, which is set to a tuple of fields to use to create filters along the right side of the change list page. For date fields, Django provides shortcuts to filter the list to \u201cToday,\u201d \u201cPast 7 days,\u201d \u201cThis month\u201d and \u201cThis year\u201d \u2013 shortcuts that Django\u2019s developers have found hit the common cases for filtering by date. Figure 5-10 shows what that looks like.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter wp-image-128587 size-full\" src=\"https:\/\/www.vskills.in\/lms\/wp-content\/uploads\/2016\/07\/19.jpg\" alt=\"\" width=\"1161\" height=\"646\"><\/p>\n<p>list_filter also works on fields of other types, not just DateField. (Try it with BooleanField and ForeignKey fields, for example.) The filters show up as long as there are at least 2 values to choose from. Another way to offer date filters is to use the date_hierarchy admin option, like this:<\/p>\n<pre>class BookAdmin(admin.ModelAdmin):\nlist_display = ('title', 'publisher','publication_date')\nlist_filter = ('publication_date',)\ndate_hierarchy = 'publication_date'<\/pre>\n<p>With this in place, the change list page gets a date drill-down navigation bar at the top of the list, as shown in figure below. It starts with a list of available years, then drills down into months and individual days.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter wp-image-128587 size-full\" src=\"https:\/\/www.vskills.in\/lms\/wp-content\/uploads\/2016\/07\/19.jpg\" alt=\"\" width=\"1161\" height=\"646\"><br>\nNote that date_hierarchy takes a string, not a tuple, because only one date field can be used to make the hierarchy. Finally, let\u2019s change the default ordering so that books on the change list page are always ordered descending by their publication date.<\/p>\n<p>By default, the change list orders objects according to their model\u2019s ordering within class Meta \u2013 but you haven\u2019t specified this ordering value, then the ordering is undefined.<\/p>\n<pre>class BookAdmin(admin.ModelAdmin):\nlist_display = ('title', 'publisher','publication_date')\nlist_filter = ('publication_date',)\ndate_hierarchy = 'publication_date'\nordering = ('-publication_date',)<\/pre>\n<p>This admin ordering option works exactly as the ordering in models\u2019 class Meta, except that it only uses the first field name in the list. Just pass a list or tuple of field names, and add a minus sign to a field to use descending sort order.<\/p>\n<p>Reload the book change list to see this in action. Note that the \u201cPublication date\u201d header now includes a small arrow that indicates which way the records are sorted.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter wp-image-128588 size-full\" src=\"https:\/\/www.vskills.in\/lms\/wp-content\/uploads\/2016\/07\/20.jpg\" alt=\"\" width=\"1161\" height=\"648\"><\/p>\n<p>We\u2019ve covered the main change list options here. Using these options, you can make a very powerful, production-ready data-editing interface with only a few lines of code.<\/p>\n<p><strong>Customizing Edit Forms<\/strong> &#8211; Just as the change list can be customized, edit forms can be customized in many ways. First, let\u2019s customize the way fields are ordered. By default, the order of fields in an edit form corresponds to the order they\u2019re defined in the model. We can change that using the fields option in our ModelAdmin subclass:<\/p>\n<pre>class BookAdmin(admin.ModelAdmin):\nlist_display = ('title', 'publisher', 'publication_date')\nlist_filter = ('publication_date',)\ndate_hierarchy = 'publication_date'\nordering = ('-publication_date',)\nfields = ('title', 'authors', 'publisher', 'publication_date')<\/pre>\n<p>After this change, the edit form for books will use the given ordering for fields. It\u2019s slightly more natural to have the authors after the book title. Of course, the field order should depend on your data-entry workflow. Every form is different.<\/p>\n<p>Another useful thing the fields option lets you do is to exclude certain fields from being edited entirely. Just leave out the field(s) you want to exclude. You might use this if your admin users are only trusted to edit a certain segment of your data, or if some of your fields are changed by some outside, automated process.<\/p>\n<p>For example, in our book database, we could hide the publication_date field from being editable:<\/p>\n<pre>class BookAdmin(admin.ModelAdmin):\nlist_display = ('title', 'publisher','publication_date')\nlist_filter = ('publication_date',)\ndate_hierarchy = 'publication_date'\nordering = ('-publication_date',)\nfields = ('title', 'authors', 'publisher')<\/pre>\n<p>As a result, the edit form for books doesn\u2019t offer a way to specify the publication date. This could be useful, say, if you\u2019re an editor who prefers that his authors not push back publication dates. (This is purely a hypothetical example, of course.) When a user uses this incomplete form to add a new book, Django will simply set the publication_date to None \u2013 so make sure that field has null=True.<\/p>\n<p>Another commonly used edit-form customization has to do with many-to-many fields. As we\u2019ve seen on the edit form for books, the admin site represents each ManyToManyField as a multiple-select box, which is the most logical HTML input widget to use \u2013 but multiple-select boxes can be difficult to use. If you want to select multiple items, you have to hold down the control key, or command on a Mac, to do so.<\/p>\n<p>The admin site helpfully inserts a bit of text that explains this, but it still gets unwieldy when your field contains hundreds of options. The admin site\u2019s solution is filter_horizontal. Let\u2019s add that to BookAdmin and see what it does.<\/p>\n<pre>class BookAdmin(admin.ModelAdmin):\nlist_display = ('title', 'publisher','publication_date')\nlist_filter = ('publication_date',)\ndate_hierarchy = 'publication_date'\nordering = ('-publication_date',)\nfilter_horizontal = ('authors',)<\/pre>\n<p>(If you\u2019re following along, note that I\u2019ve also removed the fields option to display all the fields in the edit form.) Reload the edit form for books, and you\u2019ll see that the \u201cAuthors\u201d section now uses a fancy JavaScript filter interface that lets you search through the options dynamically and move specific authors from \u201cAvailable authors\u201d to the \u201cChosen authors\u201d box, and vice versa (Figure 5-13).<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter wp-image-128589 size-full\" src=\"https:\/\/www.vskills.in\/lms\/wp-content\/uploads\/2016\/07\/21.jpg\" alt=\"\" width=\"1161\" height=\"947\"><\/p>\n<p>I\u2019d highly recommend using filter_horizontal for any ManyToManyField that has more than 10 items. It\u2019s far easier to use than a simple multiple-select widget. Also, note you can use filter_horizontal for multiple fields \u2013 just specify each name in the tuple.<\/p>\n<p>ModelAdmin classes also support a filter_vertical option. This works exactly as filter_horizontal, but the resulting JavaScript interface stacks the two boxes vertically instead of horizontally. It\u2019s a matter of personal taste.<\/p>\n<p>filter_horizontal and filter_vertical only work on ManyToManyField fields, not ForeignKey fields. By default, the admin site uses simple &lt;select&gt; boxes for ForeignKey fields, but, as for ManyToManyField, sometimes you don\u2019t want to incur the overhead of having to select all the related objects to display in the drop-down.<\/p>\n<pre>For example, if our book database grows to include thousands of publishers, the \u201cAdd book\u201d form could take a while to load, because it would have to load every publisher for display in the &lt;select&gt; box. The way to fix this is to use an option called raw_id_fields:\nclass BookAdmin(admin.ModelAdmin):\nlist_display = ('title', 'publisher','publication_date')\nlist_filter = ('publication_date',)\ndate_hierarchy = 'publication_date'\nordering = ('-publication_date',)\nfilter_horizontal = ('authors',)\nraw_id_fields = ('publisher',)<\/pre>\n<p>Set this to a tuple of ForeignKey field names, and those fields will be displayed in the admin with a simple text input box (&lt;input type=&#8221;text&#8221;&gt;) instead of a &lt;select&gt;.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter wp-image-128590 size-full\" src=\"https:\/\/www.vskills.in\/lms\/wp-content\/uploads\/2016\/07\/22.jpg\" alt=\"\" width=\"1161\" height=\"947\"><\/p>\n<p>What do you enter in this input box? The database ID of the publisher. Given that humans don\u2019t normally memorize database IDs, there\u2019s also a magnifying-glass icon that you can click to pull up a pop-up window, from which you can select the publisher to add.<\/p>\n<h3>Users, Groups, and Permissions<\/h3>\n<p>Because you\u2019re logged in as a superuser, you have access to create, edit, and delete any object. Naturally, different environments require different permission systems \u2013 not everybody can or should be a superuser.<\/p>\n<p>Django\u2019s admin site uses a permissions system that you can use to give specific users access only to the portions of the interface that they need. These user accounts are meant to be generic enough to be used outside of the admin interface, but we\u2019ll just treat them as admin user accounts for now.<\/p>\n<p>You can edit users and permissions through the admin interface just like any other object. We saw this earlier, when we played around with the User and Group sections of the admin. User objects have the standard username, password, e-mail and real name fields you might expect, along with a set of fields that define what the user is allowed to do in the admin interface.<\/p>\n<p>First, there\u2019s a set of three boolean flags:<\/p>\n<ul>\n<li>The active flag controls whether the user is active at all. If this flag is off and the user tries to log in, they won\u2019t be allowed in, even with a valid password.<\/li>\n<li>The staff flag controls whether the user is allowed to log in to the admin interface (i.e., whether that user is considered a staff member in your organization). Since this same user system can be used to control access to public (i.e., non-admin) sites, this flag differentiates between public users and administrators.<\/li>\n<li>The superuser flag gives the user full access to add, create and delete any item in the admin interface. If a user has this flag set, then all regular permissions (or lack thereof) are ignored for that user.<\/li>\n<\/ul>\n<p>Normal admin users \u2013 that is, active, non-superuser staff members \u2013 are granted admin access through assigned permissions. Each object editable through the admin interface (e.g., books, authors, publishers) has three permissions: a create permission, an edit permission and a delete permission.<\/p>\n<p>Assigning permissions to a user grants the user access to do what is described by those permissions. When you create a user, that user has no permissions, and it\u2019s up to you to give the user specific permissions. For example, you can give a user permission to add and change publishers, but not permission to delete them.<\/p>\n<p>Note that these permissions are defined per-model, not per-object \u2013 so they let you say \u201cJohn can make changes to any book,\u201d but they don\u2019t let you say \u201cJohn can make changes to any book published by Apress.\u201d The latter functionality, per-object permissions, is a bit more complicated and is outside the scope of this book but is covered in the Django documentation.<\/p>\n<p>Access to edit users and permissions is also controlled by this permission system. If you give someone permission to edit users, they will be able to edit their own permissions, which might not be what you want! Giving a user permission to edit users is essentially turning a user into a superuser.<\/p>\n<p>You can also assign users to groups. A group is simply a set of permissions to apply to all members of that group. Groups are useful for granting identical permissions to a subset of users.<\/p>\n<h3>When and Why to Use the Admin Interface \u2013 And When Not to<\/h3>\n<p>After having worked through, you should have a good idea of how to use Django\u2019s admin site. But I want to make a point of covering when and why you might want to use it \u2013 and when not to use it.<\/p>\n<p>Django\u2019s admin site shines when nontechnical users need to be able to enter data; that\u2019s the purpose behind the feature, after all. At the newspaper where Django was first developed, development of a typical online feature \u2013 say, a special report on water quality in the municipal supply \u2013 would go something like this:<\/p>\n<ul>\n<li>&nbsp;The reporter responsible for the project meets with one of the developers and describes the available data.<\/li>\n<li>The developer designs Django models to fit this data and then opens up the admin site to the reporter.<\/li>\n<li>The reporter inspects the admin site to point out any missing or extraneous fields \u2013 better now than later. The developer changes the models iteratively.<\/li>\n<li>When the models are agreed upon, the reporter begins entering data using the admin site. At the same time, the programmer can focus on developing the publicly accessible views\/templates (the fun part!).<\/li>\n<\/ul>\n<p>In other words, the raison d\u2019etre of Django\u2019s admin interface is facilitating the simultaneous work of content producers and programmers. However, beyond these obvious data entry tasks, the admin site is useful in a few other cases:<\/p>\n<ul>\n<li>Inspecting data models. Once you\u2019ve defined a few models, it can be quite useful to call them up in the admin interface and enter some dummy data. In some cases, this might reveal data-modelling mistakes or other problems with your models.<\/li>\n<li>Managing acquired data. For applications that rely on data coming from external sources (e.g., users or web crawlers), the admin site gives you an easy way to inspect or edit this data. You can think of it as a less powerful, but more convenient, version of your database\u2019s command-line utility.<\/li>\n<li>Quick and dirty data-management apps. You can use the admin site to build yourself a very lightweight data management app \u2013 say, to keep track of expenses. If you\u2019re just building something for your own needs, not for public consumption, the admin site can take you a long way. In this sense, you can think of it as a beefed up, relational version of a spreadsheet.<\/li>\n<\/ul>\n<p>The admin site is not, however, a be-all and end-all. It\u2019s not intended to be a public interface to data, nor is it intended to allow for sophisticated sorting and searching of your data. As I said at the earlier, it\u2019s for trusted site administrators. Keeping this sweet spot in mind is the key to effective admin-site usage.<\/p>\n\n\n<p><a href=\"https:\/\/www.vskills.in\/certification\/tutorial\/certified-django-developer\/\" target=\"_blank\" rel=\"noreferrer noopener\">Back to Tutorial<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>When you ran django-admin startproject mysite, Django created and configured the default admin site for you. All that you need to do is create an admin user (superuser) and then you can log into the admin site. If you are using Visual Studio, you don\u2019t need to complete this next step at the command line,&#8230;<\/p>\n","protected":false},"author":1,"featured_media":0,"parent":0,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"","meta":{"footnotes":""},"categories":[8655],"tags":[8762],"class_list":["post-75643","page","type-page","status-publish","hentry","category-django-web-development","tag-using-the-admin-interface"],"acf":[],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v24.5 - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>Using the Admin Interface - Tutorial<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.vskills.in\/certification\/tutorial\/using-the-admin-interface\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Using the Admin Interface - Tutorial\" \/>\n<meta property=\"og:description\" content=\"When you ran django-admin startproject mysite, Django created and configured the default admin site for you. All that you need to do is create an admin user (superuser) and then you can log into the admin site. If you are using Visual Studio, you don\u2019t need to complete this next step at the command line,...\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.vskills.in\/certification\/tutorial\/using-the-admin-interface\/\" \/>\n<meta property=\"og:site_name\" content=\"Tutorial\" \/>\n<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/vskills.in\/\" \/>\n<meta property=\"article:modified_time\" content=\"2024-04-12T08:47:14+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/www.vskills.in\/lms\/wp-content\/uploads\/2016\/07\/8.png\" \/>\n<meta name=\"twitter:label1\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data1\" content=\"28 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"WebPage\",\"@id\":\"https:\/\/www.vskills.in\/certification\/tutorial\/using-the-admin-interface\/\",\"url\":\"https:\/\/www.vskills.in\/certification\/tutorial\/using-the-admin-interface\/\",\"name\":\"Using the Admin Interface - Tutorial\",\"isPartOf\":{\"@id\":\"https:\/\/www.vskills.in\/certification\/tutorial\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/www.vskills.in\/certification\/tutorial\/using-the-admin-interface\/#primaryimage\"},\"image\":{\"@id\":\"https:\/\/www.vskills.in\/certification\/tutorial\/using-the-admin-interface\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/www.vskills.in\/lms\/wp-content\/uploads\/2016\/07\/8.png\",\"datePublished\":\"2020-01-20T05:54:53+00:00\",\"dateModified\":\"2024-04-12T08:47:14+00:00\",\"breadcrumb\":{\"@id\":\"https:\/\/www.vskills.in\/certification\/tutorial\/using-the-admin-interface\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/www.vskills.in\/certification\/tutorial\/using-the-admin-interface\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/www.vskills.in\/certification\/tutorial\/using-the-admin-interface\/#primaryimage\",\"url\":\"https:\/\/www.vskills.in\/lms\/wp-content\/uploads\/2016\/07\/8.png\",\"contentUrl\":\"https:\/\/www.vskills.in\/lms\/wp-content\/uploads\/2016\/07\/8.png\"},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/www.vskills.in\/certification\/tutorial\/using-the-admin-interface\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/www.vskills.in\/certification\/tutorial\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Using the Admin Interface\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/www.vskills.in\/certification\/tutorial\/#website\",\"url\":\"https:\/\/www.vskills.in\/certification\/tutorial\/\",\"name\":\"Tutorial\",\"description\":\"Vskills - A initiative in elearning and certification\",\"publisher\":{\"@id\":\"https:\/\/www.vskills.in\/certification\/tutorial\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/www.vskills.in\/certification\/tutorial\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Organization\",\"@id\":\"https:\/\/www.vskills.in\/certification\/tutorial\/#organization\",\"name\":\"Vskills\",\"url\":\"https:\/\/www.vskills.in\/certification\/tutorial\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/www.vskills.in\/certification\/tutorial\/#\/schema\/logo\/image\/\",\"url\":\"https:\/\/www.vskills.in\/certification\/tutorial\/wp-content\/uploads\/2017\/07\/vskills-min-logo.jpg\",\"contentUrl\":\"https:\/\/www.vskills.in\/certification\/tutorial\/wp-content\/uploads\/2017\/07\/vskills-min-logo.jpg\",\"width\":73,\"height\":55,\"caption\":\"Vskills\"},\"image\":{\"@id\":\"https:\/\/www.vskills.in\/certification\/tutorial\/#\/schema\/logo\/image\/\"},\"sameAs\":[\"https:\/\/www.facebook.com\/vskills.in\/\",\"https:\/\/x.com\/vskills_in\",\"https:\/\/www.linkedin.com\/company-beta\/1371554\/\",\"https:\/\/www.youtube.com\/channel\/UCMWnscxPwRF_PqXo9B7q_Tw\"]}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Using the Admin Interface - Tutorial","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.vskills.in\/certification\/tutorial\/using-the-admin-interface\/","og_locale":"en_US","og_type":"article","og_title":"Using the Admin Interface - Tutorial","og_description":"When you ran django-admin startproject mysite, Django created and configured the default admin site for you. All that you need to do is create an admin user (superuser) and then you can log into the admin site. If you are using Visual Studio, you don\u2019t need to complete this next step at the command line,...","og_url":"https:\/\/www.vskills.in\/certification\/tutorial\/using-the-admin-interface\/","og_site_name":"Tutorial","article_publisher":"https:\/\/www.facebook.com\/vskills.in\/","article_modified_time":"2024-04-12T08:47:14+00:00","og_image":[{"url":"https:\/\/www.vskills.in\/lms\/wp-content\/uploads\/2016\/07\/8.png","type":"","width":"","height":""}],"twitter_misc":{"Est. reading time":"28 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"WebPage","@id":"https:\/\/www.vskills.in\/certification\/tutorial\/using-the-admin-interface\/","url":"https:\/\/www.vskills.in\/certification\/tutorial\/using-the-admin-interface\/","name":"Using the Admin Interface - Tutorial","isPartOf":{"@id":"https:\/\/www.vskills.in\/certification\/tutorial\/#website"},"primaryImageOfPage":{"@id":"https:\/\/www.vskills.in\/certification\/tutorial\/using-the-admin-interface\/#primaryimage"},"image":{"@id":"https:\/\/www.vskills.in\/certification\/tutorial\/using-the-admin-interface\/#primaryimage"},"thumbnailUrl":"https:\/\/www.vskills.in\/lms\/wp-content\/uploads\/2016\/07\/8.png","datePublished":"2020-01-20T05:54:53+00:00","dateModified":"2024-04-12T08:47:14+00:00","breadcrumb":{"@id":"https:\/\/www.vskills.in\/certification\/tutorial\/using-the-admin-interface\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.vskills.in\/certification\/tutorial\/using-the-admin-interface\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.vskills.in\/certification\/tutorial\/using-the-admin-interface\/#primaryimage","url":"https:\/\/www.vskills.in\/lms\/wp-content\/uploads\/2016\/07\/8.png","contentUrl":"https:\/\/www.vskills.in\/lms\/wp-content\/uploads\/2016\/07\/8.png"},{"@type":"BreadcrumbList","@id":"https:\/\/www.vskills.in\/certification\/tutorial\/using-the-admin-interface\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/www.vskills.in\/certification\/tutorial\/"},{"@type":"ListItem","position":2,"name":"Using the Admin Interface"}]},{"@type":"WebSite","@id":"https:\/\/www.vskills.in\/certification\/tutorial\/#website","url":"https:\/\/www.vskills.in\/certification\/tutorial\/","name":"Tutorial","description":"Vskills - A initiative in elearning and certification","publisher":{"@id":"https:\/\/www.vskills.in\/certification\/tutorial\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.vskills.in\/certification\/tutorial\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Organization","@id":"https:\/\/www.vskills.in\/certification\/tutorial\/#organization","name":"Vskills","url":"https:\/\/www.vskills.in\/certification\/tutorial\/","logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.vskills.in\/certification\/tutorial\/#\/schema\/logo\/image\/","url":"https:\/\/www.vskills.in\/certification\/tutorial\/wp-content\/uploads\/2017\/07\/vskills-min-logo.jpg","contentUrl":"https:\/\/www.vskills.in\/certification\/tutorial\/wp-content\/uploads\/2017\/07\/vskills-min-logo.jpg","width":73,"height":55,"caption":"Vskills"},"image":{"@id":"https:\/\/www.vskills.in\/certification\/tutorial\/#\/schema\/logo\/image\/"},"sameAs":["https:\/\/www.facebook.com\/vskills.in\/","https:\/\/x.com\/vskills_in","https:\/\/www.linkedin.com\/company-beta\/1371554\/","https:\/\/www.youtube.com\/channel\/UCMWnscxPwRF_PqXo9B7q_Tw"]}]}},"_links":{"self":[{"href":"https:\/\/www.vskills.in\/certification\/tutorial\/wp-json\/wp\/v2\/pages\/75643","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.vskills.in\/certification\/tutorial\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/www.vskills.in\/certification\/tutorial\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/www.vskills.in\/certification\/tutorial\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.vskills.in\/certification\/tutorial\/wp-json\/wp\/v2\/comments?post=75643"}],"version-history":[{"count":4,"href":"https:\/\/www.vskills.in\/certification\/tutorial\/wp-json\/wp\/v2\/pages\/75643\/revisions"}],"predecessor-version":[{"id":83344,"href":"https:\/\/www.vskills.in\/certification\/tutorial\/wp-json\/wp\/v2\/pages\/75643\/revisions\/83344"}],"wp:attachment":[{"href":"https:\/\/www.vskills.in\/certification\/tutorial\/wp-json\/wp\/v2\/media?parent=75643"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.vskills.in\/certification\/tutorial\/wp-json\/wp\/v2\/categories?post=75643"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.vskills.in\/certification\/tutorial\/wp-json\/wp\/v2\/tags?post=75643"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}