Установить значение по умолчанию для поля модели, основанное на значении предыдущего объекта из класса модели - PullRequest
1 голос
/ 18 июня 2020

Я установил, что менеджеры моделей запрашивают request_number последней записи в базе данных. Значение по умолчанию для номера запроса должно быть 210001 (если первая запись 2021 года) или следующий порядковый номер текущего года (20002, 20003, 20004, и т.д. c).

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

from django.db import models
import datetime


class ServiceRequestManager(models.Manager):

    def last_record(self):
        last_record_year = int(self.last().request_number[0:2])
        return last_record_year

    def last_record_request_number_plus_one(self):
        last_request_number = int(self.last().request_number) + 1
        return last_request_number

    def test(self):
        year_difference = int(datetime.date.today().strftime('%y')) - int(self.last().request_number[0:2])
        return year_difference


def number():
    year = str(datetime.date.today().strftime('%y'))  # Pulls last two digits of the year
    # previous_record_year = ServiceRequestManager.last_record
    # new_request_number = ServiceRequestManager.last_record_request_number_plus_one
    # current_record_year = int(datetime.date.today().strftime('%y'))
    if int(year) > ServiceRequestManager.last_record(): # TypeError: last_record() missing 1 required positional argument: 'self'
        return year
    else:
        i = 1
        i_pad = "%04d" % i  # creates 000x so default is 0001
        return year+str(i_pad)  # Creates the full request number e.g. 200001

# Need the next record to be 200002, 200003, 200004 etc until the first instance of 2021 which would be 210001, 210002, etc.


# Create your models here.
class ServiceRequest(models.Model):

    CATEGORY_CHOICES = (
        (None, ''),
        ('aircraft_repair', 'Aircraft Repair'),
        ('backshop', 'Backshop'),
        ('documentation', 'Documentation'),
        ('other', 'Other')
    )

    PRIORITY_CHOICES = (
        (None, ''),
        ('1', '1-Critical (<24 hours)'),
        ('2', '2-Urgent (1-2 Days)'),
        ('3', '3-Standard (3 Days)'),
        ('4', '4-Low (5 Days)')
    )

    timestamp = models.DateTimeField(auto_now_add=True, auto_now=False, blank=True)
    updated = models.DateTimeField(auto_now=True)
    request_number = models.CharField(max_length=6, default=number())

    objects = ServiceRequestManager()

    def __str__(self):
        return self.request_number # show the request number in admin screen

    class Meta:
        ordering = ('-request_number',) # sort request number descending in admin screen

1 Ответ

1 голос
/ 18 июня 2020

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

Если такой записи нет, мы return f'{y2}0000' (таким образом, мы "запускаем" новую последовательность), и если это так, мы анализируем ее до int, затем увеличиваем ее и получаем последние четыре цифры для создания новой:

from django.utils.timezone import now

def number():
    y2 = now().strftime('%y')
    last_request = ServiceRequest.objects.filter(
        request_number__startswith=y2
    ).order_by('-request_number').values_list('request_number', flat=True).first()
    if last_request is None:
        return f'{y2}0000'
    else:
        num = (int(last_request) + 1) % 10000
        return f'{y2}{num:04d}'

В модели мы передаем default=number, поэтому ссылка на функцию, а не результат из вызова функции. Кроме того, может быть полезно указать индекс базы данных и сделать поле уникальным (чтобы предотвратить создание двух записей с одинаковыми reference_number в базе данных):

class ServiceRequest(models.Model):
    CATEGORY_CHOICES = (
        (None, ''),
        ('aircraft_repair', 'Aircraft Repair'),
        ('backshop', 'Backshop'),
        ('documentation', 'Documentation'),
        ('other', 'Other')
    )

    PRIORITY_CHOICES = (
        (None, ''),
        ('1', '1-Critical (<24 hours)'),
        ('2', '2-Urgent (1-2 Days)'),
        ('3', '3-Standard (3 Days)'),
        ('4', '4-Low (5 Days)')
    )

    timestamp = models.DateTimeField(auto_now_add=True)
    updated = models.DateTimeField(auto_now=True)
    request_number = models.CharField(
        max_length=6,
        <b>db_index=True</b>,
        default=<b>number</b>,
        <b>unique=True</b>
    )

Возможно, четырех цифр, однако, недостаточно. Может быть более безопасно использовать, например, max_length=8, чтобы разрешить 1 000 000 запросов в год. Тем более, что некоторые номера запросов, возможно, недействительны (и поэтому будут закрыты).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...