Django, добавление исключенных свойств к представленной модели

У меня есть модель, и я исключил два поля, поля create_date и created_by. Теперь я получаю ошибку "Not Null" при использовании метода save(), потому что created_by пуст.

Я попытался добавить идентификатор пользователя в форму до метода save() следующим образом: form.cleaned_data['created_by'] = 1 и form.cleaned_data['created_by_id'] = 1. Но ничто из этого не работает.

Может кто-нибудь объяснить мне, как я могу добавить дополнительные материалы к представленной модели модели, чтобы сохранить ее?

class Location(models.Model):
    name = models.CharField(max_length = 100)
    created_by = models.ForeignKey(User)
    create_date = models.DateTimeField(auto_now=True)

class LocationForm(forms.ModelForm):
    class Meta:
        model = Location
        exclude = ('created_by', 'create_date', )

Ответ 1

Так как вы исключили поля created_by и create_date в своей форме, попытка их назначения через form.cleaned_data не имеет никакого смысла.

Вот что вы можете сделать:

Если у вас есть представление, вы можете просто использовать form.save(commit=False), а затем установить значение created_by

def my_view(request):
    if request.method == "POST":
        form = LocationForm(request.POST)
        if form.is_valid():
            obj = form.save(commit=False)
            obj.created_by = request.user
            obj.save()
        ...
        ...

`

Если вы используете Admin, вы можете переопределить метод save_model(), чтобы получить желаемый результат.

class LocationAdmin(admin.ModelAdmin):
    def save_model(self, request, obj, form, change):
        obj.created_by = request.user
        obj.save()

Ответ 2

Передайте пользователя как параметр для создания конструктора, затем используйте его для установки поля created_by экземпляра модели:

def add_location(request):
    ...
    form = LocationForm(user=request.user)
    ...

class LocationForm(forms.ModelForm):
    def __init__(self, *args, **kwargs):
        user = kwargs.pop('user')
        super(forms.ModelForm, self).__init__(*args, **kwargs)
        self.instance.created_by = user

Ответ 3

Правильное решение - передать экземпляр объекта с предварительно заполненными полями в конструктор формы модели. Таким образом, поля будут заполнены во время проверки. Присвоение значений после form.save() может привести к ошибкам проверки, если требуются поля.

LocationForm(request.POST or None, instance=Location(
    created_by=request.user,
    create_date=datetime.now(),
))

Обратите внимание, что экземпляр является несохраненным объектом, поэтому идентификатор не будет назначен до тех пор, пока форма не сохранит его.

Ответ 4

Один из способов сделать это - использовать form.save(commit = False) (doc)

Это вернет экземпляр объекта класса модели, не передавая его в базу данных.

Итак, ваша обработка может выглядеть примерно так:

form = some_form(request.POST)
location = form.save(commit=False)
user = User(pk=1)
location.created_by = user
location.create_date = datetime.now()
location.save()