Home > Software design >  Error while saving foreign key data in database using Django Model Form
Error while saving foreign key data in database using Django Model Form

Time:07-18

I have two Models for my Project, 1. Category Model and 2. Course Model

Course Model has a Foreign Key reference with my Category Model as shown below.

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)
    

Initially I was using HTML form and will be able to save the Course data under a Particular Category to the database as:

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')
        

Later I decided to move on using Django Model forms and I tried to implement the code as follows

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))

Later in the view I have saved the data as

def add_course(request):
    if request.method == 'POST':
        addcourse = AddCourseForm(request.POST, request.FILES)
        if addcourse.is_valid():
            addcourse.save()
    return redirect('/all_category')

On my HTML page I am passing the input to the 'course_category' inputfield as 1,2,3....etc as the category_id value I have rendered the field in the form as

{{form.course_category}}

On Submitting the form when my 'course_category' inputfield has value as 1, it saves the data to the database but when the inputfield value is 2 then it is not even entering to the if condition of addcourse.is_valid() in the view function.

As I'm new the Django I'm not able to find the right way to get the ForeignKey value dynamically save the data in reference to that Category. Also I want to populate the same data back to the form in case of edit.

Please guide, thanks in advance.

CodePudding user response:

After debugging the Code a little bit, I modified the init function in the AddCourseForm class as mentioned below that solved my issue but I am not it is the right way to do this or not

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))

CodePudding user response:

I don't think doing this should be that difficult, here is how you would set the course_category options in the form normally:

# 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

If you want to set a particular category in the form the you can pass an initial value in your view:

# 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})

If you then want to kill all other options entirely, you can use the initial value to set your filter:

# 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)
  • Related