Django - Передача создателя формы в форму
Я создаю сайт-аукцион. Мне нужно знать для каждого объявления, кто был его создателем (чтобы у создателей была возможность удалить объявление). Я могу вручную изменить пользователя в Django Admin, но я хочу, чтобы это автоматически сохранялось, когда кто-то создает новое объявление
Как передать создателя формы в форму?
Вот соответствующие модели:
class User(AbstractUser):
pass
class AuctionListing(models.Model):
title = models.CharField(max_length=64)
description = models.CharField(max_length=512, default="")
starting_bid = models.DecimalField(max_digits=6, decimal_places=2, default=0.01, validators=[MinValueValidator(Decimal('0.01'))])
url = models.URLField(max_length=200, blank=True)
category = models.CharField(max_length = 20)
user = models.ForeignKey(User, on_delete=models.CASCADE, db_constraint=False, related_name="items")
def __str__(self):
return self.title
Вот мой файл forms.py:
class CreateListing(forms.ModelForm):
category = forms.ModelChoiceField(queryset=Category.objects.all(), empty_label="No category")
class Meta:
model = AuctionListing
fields = ('title', 'description', 'starting_bid', 'url', 'category', 'user')
widgets = {
'title': forms.TextInput(attrs={'placeholder':'Write your listing title here...'}),
'description': forms.Textarea(attrs={'placeholder':'Write your comment here...', 'rows':3}),
}
А вот моя попытка для вида:
def create_listing(request):
form = CreateListing(request.POST)
if request.method == "POST":
if form.is_valid():
form_data = form.save()
form_data.user = request.user
form_data.save()
return HttpResponseRedirect(reverse("index"))
else:
print("RIP")
return render(request, "auctions/create_listing.html", {
"form" : CreateListing
})
auctions/create_listing.html выглядит следующим образом:
<h1> Create new listing </h1>
<form action="" method="POST">
{% csrf_token %}
<label>Name*</label>
<br>
{{ form.title }}
<br>
<label >Description*</label>
<br>
{{ form.description }}
<br>
<label >Starting bid*</label>
<br>
{{ form.starting_bid }}
<br>
<label > Image url (optional) </label>
<br>
{{ form.url }}
<br>
<label > Category (optional) </label>
<br>
{{ form.category }}
<br>
<input type="hidden" name="user" value="{{request.user}}">
<button type="submit" class="btn btn-primary save">Create your listing</button>
</form>
Ошибка, которую я получаю при этом: "BaseModelForm.init() получил неожиданный аргумент ключевого слова 'user'"
Как я могу исправить это, чтобы пользователь автоматически сохранялся каждый раз при создании объявления?
Замените {{ form.user }}
на <input type="hidden" name="user" value="{{request.user}}">
Пользователь должен приходить автоматически, поэтому вам не нужно отображать поле пользователя во фронт-энде
вышеуказанным методом вы получите зарегистрированного пользователя, но все еще трудно сохранить, так как это внешний ключ, и то, что вы получите из front-end, будет иметь строковый тип.
Лучшим предложением будет следующий код.
if form.is_valid():
form_data = form.save()
form_data.user = request.user
form_data.save()
Добавьте аргумент user
в метод __init__
формы. Вы можете установить пользователя прямо там, и нет необходимости даже отображать поле пользователя. Вы можете полностью скрыть его.
class CreateListing(forms.ModelForm):
category = forms.ModelChoiceField(queryset=Category.objects.all(), empty_label="No category")
class Meta:
model = AuctionListing
fields = ('title', 'description', 'starting_bid', 'url', 'category', 'user')
widgets = {
'title': forms.TextInput(attrs={'placeholder':'Write your listing title here...'}),
'description': forms.Textarea(attrs={'placeholder':'Write your comment here...', 'rows':3}),
'user': forms.HiddenInput(),
}
def __init__(self, *args, **kwargs):
user = kwargs.pop('user')
super().__init__(*args, **kwargs)
self.fields['user'].initial = user.id
Не забудьте использовать пользовательский kwarg в представлении:
def create_listing(request):
form = CreateListing(request.POST, user=request.user)
if request.method == "POST":
if form.is_valid():
form.save()
return HttpResponseRedirect(reverse("index"))
else:
print("RIP")
# If form is invalid you should render the same template again
# with the errors
return render(request, "auctions/create_listing.html", {"form": form})
return render(request, "auctions/create_listing.html", {
# For the empty form, this needs to be an instance of the form,
# and not a class
"form" : CreateListing(user=request.user)
})
Также вы можете заменить ваш HTML на:
{{ form.user }}