Ошибка при сохранении данных внешнего ключа в базе данных с помощью Django Model Form
У меня есть две модели для моего проекта, 1. Модель категории и 2. Модель курса
Модель курса имеет внешнюю ключевую ссылку с моей моделью категории, как показано ниже.
class Category(models.Model):
categoryname = models.CharField(max_length=200,null=True,blank=True, default="")
class Courses(models.Model):
coursename = models.CharField(max_length=200,null=True,blank=True, default="")
course_category = models.ForeignKey(Category, related_name="courses", blank=True,null=True,on_delete=models.CASCADE)
logo = models.ImageField(upload_to='courselogos', null=True, blank=True)
Изначально я использовал HTML форму и смогу сохранить данные курса по определенной категории в базу данных как:
def add_course(request):
if request.method == 'POST':
course_name = request.POST.get('coursname')
categoryid = request.POST.get('category_id')
category = Category.object.get(id=category_id)
course_logo = request.FILES.get('logo')
course = Courses(coursename=course_name, course_category=category, logo= course_logo)
course.save()
return redirect('/all_category')
Позже я решил перейти к использованию Django Model forms и попытался реализовать код следующим образом
class AddCourseForm(forms.ModelForm):
class Meta:
model = Courses
fields = ('coursename', 'course_category', 'logo')
widgets = {
'coursename' : forms.TextInput(attrs={'class':'form-control'}),
}
def __init__(self, *args, **kwargs):
category_id = kwargs.pop('category_id',1)
super(AddCourseForm, self).__init__(*args, **kwargs)
self.fields['course_category']=forms.ModelChoiceField(widget=forms.TextInput(), queryset=Category.objects.filter(id=category_id))
Позже в представлении я сохранил данные как
def add_course(request):
if request.method == 'POST':
addcourse = AddCourseForm(request.POST, request.FILES)
if addcourse.is_valid():
addcourse.save()
return redirect('/all_category')
На моей HTML-странице я передаю входные данные в поле ввода 'course_category' как 1,2,3....etc в качестве значения category_id. Я отобразил поле в форме как
{{form.course_category}}
При отправке формы, когда мое поле ввода 'course_category' имеет значение 1, оно сохраняет данные в базу данных, но когда значение поля ввода равно 2, оно даже не попадает в условие if addcourse.is_valid() в функции view.
Поскольку я новичок в Django, я не могу найти правильный способ получения значения ForeignKey для динамического сохранения данных в ссылке на эту категорию. Также я хочу вернуть эти же данные обратно в форму в случае редактирования.
Пожалуйста, подскажите, заранее спасибо.
После небольшой отладки кода я изменил функцию init в классе AddCourseForm, как указано ниже, что решило мою проблему, но я не уверен, что это правильный способ сделать это или нет
def __init__(self, *args, **kwargs):
category_id = None
for key in args[0:1]:
category_id = args[0].get('course_category')
super(AddCourseForm, self).__init__(*args, **kwargs)
self.fields['course_category']=forms.ModelChoiceField(widget=forms.TextInput(), queryset=Category.objects.filter(id=category_id))
Я не думаю, что сделать это будет так уж сложно, вот как вы обычно устанавливаете опции course_category
в форме:
# forms.py
class AddCourseForm(forms.ModelForm):
...
def __init__(self, *args, **kwargs):
self.course_categories = Category.objects.all()
super(AddCourseForm, self).__init__(*args, **kwargs)
self.fields['course_category'].queryset = self.course_categories
Если вы хотите установить определенную категорию в форме, вы можете передать начальное значение в вашем представлении:
# views.py
def add_course(request, pk):
# note: you can pass the category primary key to your view, you need to
# specify this in your URLs and then your template
course_category = Category.objects.get(pk=pk)
form = AddCourseForm(initial={'course_category': course_category})
Если вы хотите полностью исключить все другие варианты, вы можете использовать начальное значение для установки вашего фильтра:
# forms.py
class AddCourseForm(forms.ModelForm):
...
def __init__(self, *args, **kwargs):
super(AddCourseForm, self).__init__(*args, **kwargs)
self.fields['course_category'].queryset = Category.objects.filter(
pk=self.fields['course_category'].initial)