Как сделать конструктор, с помощью которого пользователь может создать шаблон, добавив в него любое поле из модели, включая вложенные поля?

У меня есть 5 сущностей, которые связаны друг с другом. Я успешно описал модели и отношения между ними. Здесь все хорошо.

Но они требуют от меня определенного конструктора, который предполагает, что администратор может в режиме пользователя (в панели администратора, или на любой другой странице) изменить внешний вид чека, который печатается для клиента, не меняя исходного кода программы ( т.е. добавить или убрать поля билета).

Например, пользователь может создать 2 шаблона чека - "обычный" и "уменьшенный".

"Обычная" проверка будет включать название рейса, маршрут, перевозчика, станцию отправления и станцию прибытия, дату отправления и дату прибытия, номер_места и т.д., а "сокращенная" - только название рейса, дату отправления и номер_места

Здесь я кратко опишу модели:

class BusStation(models.Model):
    name = models.CharField(max_length=64)
    city = models.CharField(max_length=32)
    region = models.CharField(max_length=32)

class Carrier(models.Model):
    name = models.CharField(max_length=64)
    inn_number = models.PositiveBigIntegerField(verbose_name='ИНН', unique=True)

class Itinerary(models.Model):
    name = models.CharField(max_length=64)
    number = models.CharField(max_length=64)
    departure_station = models.ForeignKey(BusStation, related_name='departure_busstations', on_delete=models.CASCADE)
    arrival_station = models.ForeignKey(BusStation, related_name='arrival_bus_stations', on_delete=models.CASCADE)

class Voyage(models.Model):
    departure_date = models.DateTimeField()
    arrival_date = models.DateTimeField()
    itinerary = models.ForeignKey(Itinerary, related_name='itineraries', on_delete=models.CASCADE)
    bus_station_platform = models.PositiveIntegerField()

class Ticket(models.Model):
    TYPE_TICKET = [
    ('1', '1'),
    ('2', '2'),
]

    passengers_name = models.CharField(max_length=128)
    voyage = models.ForeignKey(Voyage, related_name='voyages', on_delete=models.CASCADE)
    ticket_number = models.CharField(max_length=32, unique=True)
    place_number = models.PositiveSmallIntegerField()
    type_ticket = models.CharField(max_length=256, choices=TYPE_TICKET)

Я предполагаю, что мне нужно создать еще один entity и каким-то образом поместить в него поля модели Ticket, но я не уверен, что это правильно.

Любая помощь будет приветствоваться, потому что я застрял на реализации конструктора, так как не понимаю, какой подход использовать для реализации логики.

views.py

from .forms import ReducedTicketForm, RegularTicketForm

class CreateTicketFormView(FormView):
    def get_form_class(self):
        """Return the form class to use."""
        if self.request.kwargs.get('ticket_type') == 'reduced':
            return ReducedTicketForm
        return RegularTicketForm

    # if there is a need to use different templates,
    # adjust the get_template_names() method.
    # This is just optional, as you can also use a single template.
    def get_template_names(self):
        if self.request.kwargs.get('ticket_type') == 'reduced':
            return 'reduced_ticket_form.html'
        if self.request.kwargs.get('ticket_type') == 'regular':
            return 'regular_ticket_form.html'
        return super().get_template_names()

    # your code ...

forms.py

class ReducedTicketForm(forms.ModelForm):
    class Meta:
        model = Ticket
        fields = ['passengers_name', 'voyage', 'place_number']
        exclude = ['created', 'updated']


class RegularTicketForm(forms.ModelForm):
    class Meta:
        model = Ticket
        fields = ['passengers_name', 'voyage', 'ticket_number', 'place_number', 'type_ticket']
        exclude = ['created', 'updated']

urls.py

from django.urls import path
from .views import CreateTicketFormView

urlpatterns = [
    path(
        "ticket/new/<str:ticket_type>/", CreateTicketFormView.as_view(), name="ticket-create"
    ),
]

template.html

<a href="{% url 'ticket-create' ticket_type='reduced' %}">
  Create a reduced ticket
</a>
<a href="{% url 'ticket-create' ticket_type='regular' %}">
  Create a regular ticket
</a>

<hr>

{{ form }}
Вернуться на верх