Django - Как отобразить ModelForm с полем Select, указав отключенный вариант?
У меня есть следующие модели:
# Get or create a 'Not selected' category
def get_placeholder_categoy():
category, _ = ListingCategories.objects.get_or_create(category='Not selected')
return category
# Get default's category ID
def get_placeholder_category_id():
return get_placeholder_categoy().id
class ListingCategories(models.Model):
category = models.CharField(max_length=128, unique=True)
def __str__(self):
return f'{self.category}'
class Listing(models.Model):
title = models.CharField(max_length=256)
seller = models.ForeignKey(User, on_delete=models.CASCADE, related_name='listings')
description = models.TextField(max_length=5120, blank=True)
img_url = models.URLField(default='https://media.istockphoto.com/vectors/no-image-available-picture-coming-soon-missing-photo-image-vector-id1379257950?b=1&k=20&m=1379257950&s=170667a&w=0&h=RyBlzT5Jt2U87CNkopCku3Use3c_3bsKS3yj6InGx1I=')
category = models.ForeignKey(ListingCategories, on_delete=models.CASCADE, default=get_placeholder_category_id, related_name='listings')
creation_date = models.DateTimeField()
base_price = models.DecimalField(max_digits=10, decimal_places=2, validators=[
MinValueValidator(0.01),
MaxValueValidator(99999999.99)
])
С ними я имею следующую форму:
class ListingForm(ModelForm):
class Meta:
model = Listing
exclude = ['seller', 'creation_date']
widgets = {
'title': TextInput(attrs=base_html_classes),
'description': Textarea(attrs=base_html_classes),
'img_url': URLInput(attrs=base_html_classes),
'category': Select(attrs=base_html_classes),
'base_price': NumberInput(attrs=base_html_classes)
}
Одной из доступных категорий у меня является "Не выбран", поскольку я хочу позволить, чтобы, если в какой-то момент категория будет удалена, элементы могли быть переназначены в эту категорию, однако, при выводе формы я сделаю некоторую проверку в функции представления, чтобы предотвратить ее отправку, если категория "Не выбран" будет отправлена вместе с формой.
Поэтому я хочу, чтобы HTML-форма в шаблоне присваивала атрибут 'disabled' опции, соответствующей этой категории, однако, я искал уже несколько дней, не найдя ничего, что я смог бы понять настолько, чтобы попробовать это сделать.
Идеально, еще одна вещь, которую я хотел бы достичь, это возможность изменять порядок отображаемых опций на форме так, чтобы я мог перемещать на верхнюю "не выбранную", независимо от ее первичного ключа в модели.
Я знаю, что могу просто создать форму вместо формы модели, или просто изменить шаблон, чтобы вручную указать, как отображать саму форму, но я чувствую, что есть простое решение для этого либо в модели, либо в форме модели, которое я пока не нашел.
Заранее спасибо!
Я бы предложил вам использовать (в определении модели)
class Listing(models.Model):
..
category = model.ForeignKey(ListingCategories, on_delete=models.SET_NULL, null=True, related_name='listings')
..
и опционально в определении формы
class ListingForm(ModelForm):
category = forms.ModelChoiceField(ListingCategories, empty_label='Not Selected')
..
При рендеринге формы модели атрибут required
будет добавлен автоматически, а при валидации формы он также обязателен. Только при валидации базы данных поле можно оставить NULL