Какой самый элегантный или Pythonic способ инициализации объекта Django?

#python #django #object #initialization

#python #django #объект #инициализация

Вопрос:

Я новичок в Python и Django, но чувствую, что должен быть более аккуратный способ сделать это, чем я нашел.

У меня есть модель Django, которая имеет атрибут date с нетривиальным значением по умолчанию, что означает, что мне нужно немного логики для его настройки. Я пробовал несколько способов сделать это, но, к сожалению, это единственный, который пока работал для меня ( models.py внутри weeks приложения):

 def first_day_of_next_week():
    return timezone.now().date() - datetime.timedelta(days=timezone.now().date().weekday()  
        datetime.timedelta(days=7)

class Week(models.model):
    start_of_week = models.Datefield('Date of the first day of the week',
        unique=True, default=first_day_of_next_week())
 

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

Теперь, когда у меня работает модель Week , я хочу создать экземпляр weeks с Week.objects.get_or_create() помощью from views.py , но здесь я столкнулся с проблемой , что мне нужна та же first_day_of_next_week() логика, чтобы быть доступным внутри views.py . (Это то, что подтолкнуло меня к попытке перенести логику на статический или классовый метод, к которому можно было бы получить доступ views.py .) Я могу копировать first_day_of_next_week() и вставлять views.py , и это работает, но это кажется неправильным по разным причинам. Я полагаю, что я мог бы не использовать значение по умолчанию и сохранить логику для создания только недели views.py , но у меня сложилось впечатление, что предпочтительнее иметь всю логику, связанную с неделей, в модели, где это возможно.

Что бы сделал опытный программист на Python?

Комментарии:

1. «Мне очень не нравится, когда функция плавает за пределами любого подобного класса (но у меня нет опыта, чтобы знать, действительно ли это плохо). » Это неплохо. Это совершенно нормально. Функции, которые не требуют доступа к внутреннему состоянию класса, не должны быть членами класса

2. Я ответил на вопрос в названии поста, но на самом деле ваш вопрос не об этом, а об архитектуре. Чтобы понять, как организовать ваш код, вам нужно узнать, что такое уровни архитектуры и как организовать ваш код в слоях. Я могу только порекомендовать прочитать несколько книг. Есть один, который мне нравится github.com/cosmicpython/book .

3. Спасибо @juanpa.arrivillaga, это полезный указатель, но разве не все статические методы соответствуют этому критерию?

4. @Dan да, я бы согласился, staticmethod это довольно бессмысленно, и почти всегда было бы лучше как функция уровня модуля. Иногда они хороши как инструмент для организации кода / проектирования API…. Но в большую часть кода, который я написал на Python за последние 4 года профессионально, я включил, возможно, один или два staticmethod

Ответ №1:

Модели Django по-прежнему являются классами python. Вы можете использовать __init__ для инициализации, как это было задумано python:

 def first_day_of_next_week():
    return timezone.now().date() - datetime.timedelta(
        days=timezone.now().date().weekday()   datetime.timedelta(days=7)
    )


class Week(models.model):
    start_of_week = models.DateField(
        'Date of the first day of the week', unique=True
    )

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.start_of_week = self.start_of_week or first_day_of_next_week()
 

Я также рекомендую делать это вместо использования auto_now ключевых слов или auto_now_add DateField, DateTimeField, поскольку в противном случае вы не сможете передавать свои собственные значения в эти поля в тестах, django переопределит ваши значения во время сохранения в БД.