Я хотел бы скрыть поле внешнего ключа в форме, созданной из модели в представлении. Вот Модель:
class Order(models.Model):
class Meta:
ordering = ['unity_price']
item = models.ForeignKey(Item, on_delete=models.CASCADE)
user = models.ForeignKey(authModels.User, on_delete=models.CASCADE, default=1)
order_quantity = models.IntegerField(default=0)
unity_price = models.FloatField(default=0)
end_validity_date = models.DateTimeField(default=timezone.now() + datetime.timedelta(days=30))
is_sell = models.BooleanField(default=True)
def __str__(self):
if self.is_sell:
return 'sell ' + str(self.order_quantity) + ' ' + self.item.item_text + ' at ' + str(self.unity_price)
return 'buy ' + str(self.order_quantity) + ' ' + self.item.item_text + ' at ' + str(self.unity_price)
Вот Форма:
from .models import Order
class OrderForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
super(OrderForm, self).__init__(*args, **kwargs)
self.fields['user'].widget = HiddenInput()
self.fields['item'].widget = HiddenInput()
class Meta:
model = Order
fields = ('item', 'user', 'order_quantity', 'unity_price', 'end_validity_date', 'is_sell',)
А вот и вид:
class DetailView(FormMixin, generic.DetailView):
model = Item
template_name = 'bourse/detail.html'
form_class = OrderForm
def get_success_url(self):
return reverse('bourse:detail', kwargs = {'pk': self.object.id})
def get_context_data(self, **kwargs):
context = super(DetailView, self).get_context_data(**kwargs)
context['form'] = OrderForm(initial = {'post': self.object})
return context
def post(self, request, *args, **kwargs):
self.object = self.get_object()
form = self.get_form()
form.fields['item'].initial = self.get_object()
if form.is_valid():
return self.form_valid(form)
else:
return self.form_invalid(form)
def form_valid(self, form):
model_instance = form.save(commit=False)
model_instance.user = self.request.user
model_instance.item = self.get_object()
print (model_instance.item)
model_instance.save()
return super(DetailView, self).form_valid(form)
Это хорошо работает для поля «пользователь», но не для поля «элемент». Я не знаю, что поместить в model_instance.item (это должен быть объект, отображаемый текущим представлением) или в form.fields['item'].initial (это также должно быть объектом текущего представления).
С уважением,
На самом деле ошибка была в:
def get_context_data(self, **kwargs):
context = super(DetailView, self).get_context_data(**kwargs)
context['form'] = OrderForm(initial = {'item': self.object})
return context
Мне нужно было установить начальное значение «item», а не «post»!
Выньте элементы внешнего ключа из полей в метаданных формы вашей модели. Это поля, которые будут переданы в вашу форму. Итак, возьмите:
class Meta:
model = Order
fields = ('item', 'user', 'order_quantity', 'unity_price', 'end_validity_date', 'is_sell',)
и использовать только:
class Meta:
model = Order
fields = ('order_quantity', 'unity_price', 'end_validity_date', 'is_sell',)
Ввод этих значений обратно через form_valid работает хорошо, если они вам нужны.
Оглядываясь назад, я не уверен, почему вы используете подробный вид. Почему бы не использовать представление «Создать» или «Обновить»? Они предназначены для обработки форм. Наконец, да, я думаю, вы могли бы их убрать, поскольку вы объявляете форму с помощью form_class = ... и представление на основе класса должно обрабатывать экземпляр.
Я использую DetailView для отображения информации об элементе и использую форму в этом представлении для создания заказа. Разве DetailView не предназначен для отображения строки в таблице SQL?
Я не знал, что вы использовали его, чтобы сделать это. Все должно быть хорошо, не беспокойтесь.
Итак:
def get_context_data(self, **kwargs):
больше не нужен, как строка :form.fields['item'].initial = self.get_object()