Динамический запрос к базе данных и вывод отфильтрованных результатов - PullRequest
0 голосов
/ 04 ноября 2019

Python 3.7.3

django 2.2.5

mysql 5.7.27

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

  1. Активы
class Assets(models.Model):
    id = models.AutoField(db_column='Id', primary_key=True)
    assettag = models.CharField(db_column='AssetTag', unique=True, max_length=10)
    assettype = models.CharField(db_column='AssetType', max_length=150)
.........
    etc.
Сотрудники
class Employees(models.Model):
    id = models.AutoField(db_column='Id', primary_key=True)  # Field name made lowercase.
    loginname = models.CharField(db_column='LoginName', max_length=30, blank=True, null=True)
    userpass = models.CharField(db_column='UserPass', max_length=30, blank=True, null=True)
    lastname = models.CharField(db_column='LastName', max_length=50, blank=True, null=True)
    firstname = models.CharField(db_column='FirstName', max_length=50, blank=True, null=True)
.........
    etc.
Задания
class Assignments(models.Model):
    employeeid = models.ForeignKey('Employees', db_column='EmployeeId', default=0, blank=True, null=True, on_delete=models.SET_DEFAULT)
    assetid = models.ForeignKey('Assets', db_column='AssetId', default=0, blank=True, null=True, on_delete=models.SET_DEFAULT)
.........
    etc.
Items
class Item(models.Model):
    rfid_tag    = models.CharField(max_length=24, unique=True, default='',
                                   help_text="Only HEX characters allowed",)
    asset       = models.OneToOneField('Assets', default=None, null=True,
                                       on_delete=models.SET_DEFAULT,)
    date        = models.DateTimeField(name='timestamp',                     
                                       auto_now_add=True,)
    assignment = models.ForeignKey('Assignments', default=None,
                                   on_delete=models.SET_DEFAULT,)

Теперь у меня есть вид, который выглядит следующим образом:

class IndexView(generic.ListView):
    template_name = template
    context_object_name = 'item_list'

    def get_context_data(self, **kwargs):
        # call the base implementation
        context = super().get_context_data(**kwargs)
        # Add own context information
        context['count'] = Item.objects.count()
        context['employee'] = Employees.objects.filter(loginname = self.request.user.username)
        return context

    def get_queryset(self):
        query = self.request.GET.get('q')                                       
        if query:                                                               
            return Item.objects.filter(
Q(asset__assettag__icontains = query) |
Q(rfid_tag__icontains = query) |
Q(assignment__employeeid__loginname__icontains = query) |
Q(assignment__employeeid__firstname__icontains=query) |
Q(assignment__employeeid__lastname__icontains=query)
                                       ).order_by('asset__assettag')
        else:                                                                  
            return Item.objects.all()

И такой шаблон:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Inventory</title>
</head>
<body>
    {% extends "pages/base.html" %}
    {% block content %}
        <div>
            <form method="GET" action=".">
                <input type="text" name="q" placeholder="Search inventory" value="{{ request.GET.q }}"/>
                <input type="submit" class="btn btn-sm btn-info" value="Search"/>
            </form>
        </div>

        <br>
        <p>Total number of items: {{count}}</p>

        <table border="2">
            <tr>
                <th>No.</th>
                <th>RFID Tag</th>
                <th>AssetTag</th>
                <th>Owner</th>
                <th>Description</th>
                <th></th>
            </tr>
            {% for item in item_list %}
            <tr>
                <td>{{forloop.counter}}</td>
                <td> {{ item.rfid_tag }}</td>
                <td><a href = "{% url 'inventory:detail' item.asset.assettag %}"><strong>{{ item.asset.assettag }}</strong></a></td>
                <td>{{item.assignment.employeeid.firstname}} {{item.assignment.employeeid.lastname}}</td>
                <td>{{item.asset.description}}</td>
                <td>
                    <a href="{% url 'inventory:remove' item.asset.assettag %}" class="btn btn-sm btn-outline-primary py-0" role="button">Delete</a>
                </td>
            </tr>
            {% endfor %}
        </table>
    {% endblock %}
</body>
</html>

В текущей форме таблица «Элемент» имеет ссылку на таблицу «Назначения», поэтому каждый раз, когда я создаю новую запись, я выбираю последнюю из «Назначений» и устанавливаю ее как ForiegnKey. Это позволяет мне иметь быстрые и простые параметры фильтрации, как вы видите в методе get_queryset выше. Я могу отображать и выполнять поиск по сотруднику, просто отфильтровывая набор запросов Item.

До этого момента все было хорошо, все работает именно так, как я хочу. За исключением того, что Assignments не описывает уникальные ассоциации между Assets и Employees, но ведет запись. Например, если у меня есть актив «A», присвоенный сотруднику «X», а затем перенесите его на сотрудника «Y», он создаст новую запись в таблице Assignment. Таким образом, последняя запись для текущего актива является фактическим текущим назначением. Эта база данных используется двумя различными приложениями. Одна обрабатывает устаревшие таблицы и все операции, а другая предназначена только для просмотра старой базы данных и отображения вывода.

Я думал об этом, но в настоящее время не знаю, как к нему подойти. Если я удалю поле assignment из модели Item, я не знаю, как отобразить таблицу в шаблоне, чтобы показать владельца текущего актива. Если бы я хотел получить список, основанный на владельце, я бы не знал, что сделал бы это.

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

Любые предложения будут оценены.

...