Getting started¶
Django already gives a solid foundation for building apps. Trionyx add some improvements like auto loading signals/forms/cron’s. It also add new things as default views/api/background tasks (celery).
In this getting started guide we will create a new app, to show you a little of the basics on how Trionyx work and what it can do.
This guide assumes you have followed the installation instructions, and you are now in the root of your new project with the virtual environment active
This guide requires no previous knowledge of Django, but it wont go in depth on how Django works
Your first app¶
First we need to create a new app. Default Trionyx structure all apps go in the apps folder. To create a base app use the following manage command:
./manage.py create_app knowledgebase
In your apps folder should be your new app knowledgebase. For using the app we need to add it the INSTALLED_APPS:
# config/settings/base.py
# ...
INSTALLED_APPS += [
'apps.knowledgebase',
]
# ...
File structure¶
A Trionyx file structure looks as follows. The ones marked as bold, are the ones you typically use in a Trionyx app. The others are used with a Django app and can be used if you need more customization.
- <app name>
- migrations: DB migrations, these are auto generated by Django
- static: folder with your static files (js/css/images/icons)
- templates: HTML template files
- apps.py: Contains the app and model configuration
- cron.py: Cron configuration
- forms.py: Create and register your forms.
- layouts.py: Create your layouts
- models.py: Define your models
- tasks.py: Create your background tasks
- urls.y: Define your custom urls
- views.py: Create your custom views
Create model¶
We need a model to store our articles, this is just a simple Django model. Only difference is that we extend from BaseModel that add some extra Trionyx fields and functions.
# apps/knowledgebase/models.py
from trionyx import models
from django.contrib.contenttypes import fields
class Article(models.BaseModel):
title = models.CharField(max_length=255)
content = models.TextField()
# Generic relation so that different model types can be linked
# More info: https://docs.djangoproject.com/en/2.2/ref/contrib/contenttypes/#generic-relations
linked_object_type = models.ForeignKey(
'contenttypes.ContentType',
models.SET_NULL,
blank=True,
null=True,
)
linked_object_id = models.BigIntegerField(blank=True, null=True)
linked_object = fields.GenericForeignKey('linked_object_type', 'linked_object_id')
After you created the model you need to make a migration (tells the database what to do). And then run the migration to create the database table.
./manage.py makemigrations ./manage.py migrate
If you run your project with make run and you login on it. You will see the menu has a Knowledgebase -> Article entry. You can create/view/edit articles but default list view is only id, and form is not user friendly.
Custom Form¶
Lets update the create and edit form to only show the title and content. And improve the content form field by using a wysiwyg editor.
# apps/knowledgebase/forms.py
from trionyx import forms
from .models import Article
@forms.register(default_create=True, default_edit=True)
class ArticleForm(forms.ModelForm):
content = forms.Wysiwyg()
# We are going to use this later
linked_object_type = forms.ModelChoiceField(ContentType.objects.all(), required=False, widget=forms.HiddenInput())
linked_object_id = forms.IntegerField(required=False, widget=forms.HiddenInput())
class Meta:
model = Article
fields = ['title', 'content']
If you refresh your page you should see an improved create form. When you created an article it is rendered with a simple default layout, we are going to change that later. First do some configuration so that there is a better verbose name, one menu item and a better default list view.
Model configuration¶
You can configure your model in the apps.py, lets change some for Article:
# apps/knowledgebase/apps.py
from trionyx.trionyx.apps import BaseConfig, ModelConfig
class Config(BaseConfig):
"""Knowledgebase configuration"""
name = 'apps.knowledgebase'
verbose_name = 'Knowledgebase'
class Article(ModelConfig):
# Improve default list view for users
list_default_fields = ['created_at', 'created_by', 'title']
# Set a clear verbose name instead of 'Article(1)'
verbose_name = '{title}'
# Move menu item to root and set a nice icon
menu_root = True
menu_icon = 'fa fa-book'
If you take a look now at the list view it looks much more informative. And the extra submenu is also replaced by only one menu item with a nice icon.
Custom Layout¶
Lets update the layout to remove some unnecessary fields and add some new ones.
Layouts are build with components, so you dont need to write HTML.
If you need something custom and dont want to build everything in HTML.
There is the trionyx.layout.HtmlTemplate
component that renders a given django template and context.
# apps/knowledgebase/layouts.py
from trionyx.views import tabs
from trionyx.layout import Column12, Panel, TableDescription
#register a new tab default this will be `general`
@tabs.register('knowledgebase.article')
def article_layout(obj):
return Column12(
Panel(
obj.title, # For panel the first argument is the title,
# all other arguments are components
TableDescription(
'created_by',
'created_at',
'updated_at',
'content',
)
)
)
This looks nice for your model, lets use that generic field that we created on the model and form. As you can see with the tab register you can create a tab for every model you want. We are going to at a knowledgebase tab to the admin -> users:
# apps/knowledgebase/layouts.py
from trionyx.views import tabs
from trionyx.layout import Column12, Panel, TableDescription, Button, Component, Html
from django.contrib.contenttypes.models import ContentType
from trionyx.urls import model_url
from .models import Article
# ...
@tabs.register('trionyx.user', code='knowledgebase')
def user_layout(obj):
content_type = ContentType.objects.get_for_model(obj)
return Column12(
# Render a create button
Button(
'create article',
url=model_url(Article, 'dialog-create', params={
'linked_object_type': content_type.id,
'linked_object_id': obj.id,
}),
dialog=True,
dialog_reload_tab='knowledgebase',
css_class='btn btn-flat bg-theme btn-block'
),
# Render every article in a new Panel
*[
Panel(
art.title,
TableDescription(
'created_by',
'created_at',
'updated_at',
# Components that accept fields can do so in different formats
# Default is string of field name and it will get the label and value
{
'label': 'Content',
'value': Component(
Html(art.content),
Button(
'Edit',
url=model_url(art, 'dialog-edit'),
dialog=True,
dialog_reload_tab='knowledgebase',
css_class='btn btn-flat bg-theme btn-block'
),
)
},
object=art,
)
) for art in Article.objects.filter(
linked_object_type=content_type,
linked_object_id=obj.id,
)
]
)
If you reload the page on a user you will see a new tab knowledgebase. Articles that you create here are shown in the tab.
Signals¶
Django uses signals to allow you to get notifications on certain events from other apps. In this example we are going to use signals on our own Model to send an email to all users when a new article is created.
# apps/knowledgebase/signals.py
from django.db.models.signals import post_save
from django.dispatch import receiver
from trionyx.trionyx.models import User
from .models import Article
@receiver(post_save, sender=Article)
def notify_users(sender, instance, created=False, **kwargs):
if created:
for user in User.objects.all():
user.send_email(
subject=f"New Article: {instance.title}",
body=instance.content,
)
You can find more information about signals here, Only thing that Trionyx does is auto import signals.py from all apps.
Background Task¶
Trionyx uses celery for background tasks, it comes preconfigured with 3 queue’s. For more information go here. For our app we are going to use a schedulad background task to send a summary every week.
# apps/knowledgebase/tasks.py
from trionyx.tasks import shared_task
from django.utils import timezone
from trionyx.trionyx.models import User
from .models import Article
@shared_task()
def email_summary():
count = Article.objects.filter(created_at__gt=timezone.now() - timezone.timedelta(days=7)).count()
for user in User.objects.all():
user.send_email(
subject=f"There are {count} new articles",
body=f"There are {count} new articles",
)
To make this task run every week we need to add it to the cron. You can do this from inside your app by creating a cron.py.
# apps/knowledgebase/cron.py
from celery.schedules import crontab
schedule = {
'article-summary-every-sunday': {
'task': 'apps.knowledgebase.tasks.email_summary',
'schedule': crontab(minute=0, hour=0, day_of_week=0)
},
}
Now email_summary will be run every sunday. For more information on scheduling go here
API¶
If you go to http://localhost:8000/api/ you can see that Trionyx automatically created an API entry point. Trionyx make use of the Django REST framework you can easily create your own endpoint or change the serializer user by the generated end point.
# apps/knowledgebase/serializers.py or apps/knowledgebase/api/serializers.py
from trionyx.api import serializers
from trionyx.trionyx.models import User
from .models import Article
class UserSerializer(serializers.ModelSerializer):
class Meta:
model = User
fields = ['id', 'email', 'first_name', 'last_name']
@serializers.register
class UserSerializer(serializers.ModelSerializer):
created_by = UserSerializer()
class Meta:
model = Article
fields = ['created_by', 'title', 'content']
I hope you have a better understanding on how to use Trionyx. And that it can help you build you business application with the focus on your data and processes.