Introduction to Django part 2
In the first part, I've shown how to start a new project on Django, as well as define new models and add already existing models.
This time, I'll introduce an admin panel, available out of the box and how it can be useful.
Important note: do not expect that if you try to repeat actions from this post it will work for you, it does not. During the article, I had to do some fixes in the django-iris project, and even in DB-API driver made by InterSystems to fix some issues there as well, and I think this driver is still in development, and we will get more stable driver in future. Let's decide that this article only explains how it could be if we would have all done.
Let's return to our code and see what we have in urls.py, the main entrypoint for all web requests.
"""main URL Configuration
The `urlpatterns` list routes URLs to views. For more information please see:
https://docs.djangoproject.com/en/4.0/topics/http/urls/
Examples:
Function views
1. Add an import: from my_app import views
2. Add a URL to urlpatterns: path('', views.home, name='home')
Class-based views
1. Add an import: from other_app.views import Home
2. Add a URL to urlpatterns: path('', Home.as_view(), name='home')
Including another URLconf
1. Import the include() function: from django.urls import include, path
2. Add a URL to urlpatterns: path('blog/', include('blog.urls'))
"""
from django.contrib import admin
from django.urls import path
urlpatterns = [
path('admin/', admin.site.urls),
]
You may see, that there is already URL admin defined there
Let's start development server, by command
python manage.py runserver
If you go by URL http://localhost:8000/admin, you will the login form to Django administration
.png)
To enter here, we need some user, and we can create it with this command
$ python manage.py createsuperuser
Username (leave blank to use 'daimor'): admin
Email address: admin@example.com
Password:
Password (again):
The password is too similar to the username.
This password is too short. It must contain at least 8 characters.
This password is too common.
Bypass password validation and create user anyway? [y/N]: y
Superuser created successfully.We can use this login and password now. It's quite empty at the moment, but it already gives access to Groups and Users.
.png)
More data
Previously I've already installed post-and-tags package with zpm, you can do it too
zpm "install posts-and-tags"Now we can get the models for all tables (community.post, community.comment, community.tag) installed by this package
$ python manage.py inspectdb community.post community.comment community.tag > main/models.py
This will produce a bit long file, so, I put it in a spoiler
main/models.py
# This is an auto-generated Django model module.
# You'll have to do the following manually to clean this up:
# * Rearrange models' order
# * Make sure each model has one field with primary_key=True
# * Make sure each ForeignKey and OneToOneField has `on_delete` set to the desired behavior
# * Remove `managed = False` lines if you wish to allow Django to create, modify, and delete the table
# Feel free to rename the models, but don't rename db_table values or field names.
from django.db import models
class CommunityPost(models.Model):
acceptedanswerts = models.DateTimeField(db_column='AcceptedAnswerTS', blank=True, null=True) # Field name made lowercase.
author = models.CharField(db_column='Author', max_length=50, blank=True, null=True) # Field name made lowercase.
avgvote = models.IntegerField(db_column='AvgVote', blank=True, null=True) # Field name made lowercase.
commentsamount = models.IntegerField(db_column='CommentsAmount', blank=True, null=True) # Field name made lowercase.
created = models.DateTimeField(db_column='Created', blank=True, null=True) # Field name made lowercase.
deleted = models.BooleanField(db_column='Deleted', blank=True, null=True) # Field name made lowercase.
favscount = models.IntegerField(db_column='FavsCount', blank=True, null=True) # Field name made lowercase.
hascorrectanswer = models.BooleanField(db_column='HasCorrectAnswer', blank=True, null=True) # Field name made lowercase.
hash = models.CharField(db_column='Hash', max_length=50, blank=True, null=True) # Field name made lowercase.
lang = models.CharField(db_column='Lang', max_length=50, blank=True, null=True) # Field name made lowercase.
name = models.CharField(db_column='Name', max_length=250, blank=True, null=True) # Field name made lowercase.
nid = models.IntegerField(db_column='Nid', primary_key=True) # Field name made lowercase.
posttype = models.CharField(db_column='PostType', max_length=50, blank=True, null=True) # Field name made lowercase.
published = models.BooleanField(db_column='Published', blank=True, null=True) # Field name made lowercase.
publisheddate = models.DateTimeField(db_column='PublishedDate', blank=True, null=True) # Field name made lowercase.
subscount = models.IntegerField(db_column='SubsCount', blank=True, null=True) # Field name made lowercase.
tags = models.CharField(db_column='Tags', max_length=350, blank=True, null=True) # Field name made lowercase.
text = models.TextField(db_column='Text', blank=True, null=True) # Field name made lowercase.
translated = models.BooleanField(db_column='Translated', blank=True, null=True) # Field name made lowercase.
type = models.CharField(db_column='Type', max_length=50, blank=True, null=True) # Field name made lowercase.
views = models.IntegerField(db_column='Views', blank=True, null=True) # Field name made lowercase.
votesamount = models.IntegerField(db_column='VotesAmount', blank=True, null=True) # Field name made lowercase.
class Meta:
managed = False
db_table = 'community.post'
class CommunityComment(models.Model):
id1 = models.CharField(db_column='ID1', primary_key=True, max_length=62) # Field name made lowercase.
acceptedanswerts = models.DateTimeField(db_column='AcceptedAnswerTS', blank=True, null=True) # Field name made lowercase.
author = models.CharField(db_column='Author', max_length=50, blank=True, null=True) # Field name made lowercase.
avgvote = models.IntegerField(db_column='AvgVote', blank=True, null=True) # Field name made lowercase.
correct = models.BooleanField(db_column='Correct', blank=True, null=True) # Field name made lowercase.
created = models.DateTimeField(db_column='Created', blank=True, null=True) # Field name made lowercase.
hash = models.CharField(db_column='Hash', max_length=50, blank=True, null=True) # Field name made lowercase.
id = models.IntegerField(db_column='Id') # Field name made lowercase.
post = models.CharField(db_column='Post', max_length=50, blank=True, null=True) # Field name made lowercase.
text = models.TextField(db_column='Text', blank=True, null=True) # Field name made lowercase.
texthash = models.CharField(db_column='TextHash', max_length=50, blank=True, null=True) # Field name made lowercase.
type = models.CharField(db_column='Type', max_length=50) # Field name made lowercase.
votesamount = models.IntegerField(db_column='VotesAmount', blank=True, null=True) # Field name made lowercase.
class Meta:
managed = False
db_table = 'community.comment'
unique_together = (('type', 'id'),)
class CommunityTag(models.Model):
description = models.TextField(db_column='Description', blank=True, null=True) # Field name made lowercase.
name = models.TextField(db_column='Name', primary_key=True) # Field name made lowercase.
class Meta:
managed = False
db_table = 'community.tag'
The administration dashboard in Django, can be extended by developer. And it's possible to add some more tables. To do so, we need to add a new file named main/admin.py. I've added a few comments right in the code, to explain some lines.
from django.contrib import admin
# immport our community models for our tables in IRIS
from .models import(CommunityPost, CommunityComment, CommunityTag)
# register class which overrides default behaviour for model CommunityPost
@admin.register(CommunityPost)
class CommunityPostAdmin(admin.ModelAdmin):
# list of properties to show in table view
list_display = ('posttype', 'name', 'publisheddate')
# list of properties to show filter for on the right side of the tablee
list_filter = ('posttype', 'lang', 'published')
# default ordering, means from the latest date of PublishedDate
ordering = ['-publisheddate', ]
@admin.register(CommunityComment)
classCommunityCommentAdmin(admin.ModelAdmin):
# onlythistwofieldsshow, (postisnumericbyidintablepost)
list_display= ('post', 'created')
# order by date of creation
ordering = ['-created', ]
@admin.register(CommunityTag)
classCommunityTagAdmin(admin.ModelAdmin):
# notsomuchtoshowlist_display= ('name', )
Extending portal
Let's return back to our Django administration page, and see, some new items added there
.png)
On the right side, you will see the filter panel, and what's important is, that it's got all the possible values in particular fields and showed there.
Unfortunately, InterSystems SQL does not support LIMIT, OFFSET feature, expected on or another way by Django. And Django does not support TOP. So, pagination here will be shown but does not work. And no way to make it work at the moment, and I don't think will ever work, unfortunately.
You can even dive into the object, and Django will show form, with correct field types. (note: This dataset does not contain data in the Text field)
.png)
.png)
Comments object
.png)
Issues with licenses to expect on Community Edition
.png)
Even when IRIS says, you have more seats left
.png)
It allows no more than 5 connections, so, you would need to terminate one or more processes to make it work, or restart the Django server
.png)
In development, you can also limit the Django server to no threading mode, so, it will work in one process. And should not get more connections to IRIS
python manage.py runserver --nothreading
Comments
You are right there still is some issue in the IRIS DB-API, they will be fix in future release.
Well, I've managed to solve the pagination issue, it's kind of working (even with some bugs from IRIS, reported about it). And I don't like it anyway, as it's not the way it's supposed to be. But working
