Home > OS >  Why do I get this error ? ValueError: Cannot assign "'14'": "Jobs.category&
Why do I get this error ? ValueError: Cannot assign "'14'": "Jobs.category&

Time:09-29

I'm tring to add jobs to the database through a form. However I get the error " ValueError: Cannot assign "'14'": "Jobs.category" must be a "Category" instance." When I submit. I'm not sure How I can solve it. Category is a foreign key in the Jobs model. The user should be able to chose from categories already existing in the database. This displays in the form however on submitting. The error above is thrown. I'm way in over my head here. I appreciate any guidance.

forms.py

class JobForm(forms.ModelForm):

    CATEGORY_CHOICES = []        
    categories = Category.objects.all()
    for category in categories:
        CATEGORY_CHOICES.append((category.id, capwords(category.title)))

    title = forms.CharField(
                required = True,
                widget =  forms.TextInput(attrs = {'class': 'form-control ', 'placeholder': 'e.g Software Engineer'}),
                )

    category = forms.ChoiceField(
                choices = CATEGORY_CHOICES,
                required = True,
                widget = forms.Select(attrs = {'class': 'selectpicker border rounded', 'placeholder': 'select category'}),
                )
 
    class Meta:
        model = Jobs

        fields = [
            "title",
            "category",
        ]

models.py

class Category(models.Model):
    title = models.CharField(max_length= 200, null = True, blank = True)
    description = models.TextField(null = True, blank = True)
    uniqueId = models.CharField(null = True, blank = True, max_length = 100)
    categoryImage = models.ImageField(default = 'category.png', upload_to = 'upload_images')
    slug = models.SlugField(max_length = 500, unique=True, blank = True, null = True)
    
    class Meta:
        verbose_name_plural = "Categories"


class Jobs(models.Model):

    title = models.CharField(max_length=1000, null = True, blank = True)
    company = models.ForeignKey(Company, on_delete = models.CASCADE, null = True, blank = True)
    category = models.ForeignKey(Category, related_name= 'Category', on_delete = models.CASCADE, null = True, blank = True)
    location = models.CharField(max_length=1000, null = True, blank = True)
    salary = models.CharField(max_length=1000, null = True, blank = True)
    uniqueId = models.CharField(null = True, blank = True, max_length = 100)
    nature = models.CharField(max_length=100, choices=TYPE_CHOICES, default=NOT_PROVIDED)
    experience = models.CharField(max_length=100, choices=EXP_CHOICES, default=NOT_PROVIDED)
    summary = models.TextField(null = True, blank = True)
    description = models.TextField(null = True, blank = True)
    closing_date = models.DateField(blank = True, null = True)
    date_posted = models.DateField(blank = True, null = True)
    contract_type = models.CharField(max_length = 1000, null = True, blank = True)
    date_created = models.DateTimeField(default = timezone.now) 
    slug = models.SlugField(max_length = 1000, unique = True, blank = True, null = True)
 
    
    def __str__(self):
        return '{} - {}'.format(self.company, self.title)

    def get_absolute_url(self):
        return reverse('job-detail', kwargs = {'slug': self.slug})
    
    class Meta:
        verbose_name_plural = "Jobs"

views.py

def add_job(request): 
    if request.method == 'POST':
        form = JobForm(request.POST)
        if form.is_valid():
            obj = form.save(commit=False)
            obj.user = request.user
            obj.save()
            messages.success(request, 'Job added Successfully')
            return redirect('add-job')
        else:
            messages.error(request, 'Error Processing Your Request')
            context = {'form': form}
            return render(request, 'index.html', context)

    else:
        form = JobForm()
        context = {'form': form}
        return render(request, 'add-job.html', context)

CodePudding user response:

The job object expects the category to be an instance of the Category model, because it has a ForeignKey relationship defined to it. Just use a ModelChoiceField instead of the ChoiceField in the form.

class JobForm(forms.ModelForm):

    title = forms.CharField(
        required=True,
        widget=forms.TextInput(attrs={'class': 'form-control ', 'placeholder': 'e.g Software Engineer'}),
    )

    category = forms.ModelChoiceField(queryset=Category.objects.all(),
                                      required=True)

    class Meta:
        model = Jobs

        fields = [
            "title",
            "category",
        ]

CodePudding user response:

Helge's answer here explains the problem.

Quite often, its best to create relational fields indirectly rather than via a ModelForm or ModelChoiceField. Instead you add some non-relational (character, numeric, date etc) form fields and process these to identify the relevant relation. The code outline will then look something like:

if form.is_valid():  # or subclass the form_valid method of a Class based view
    info1 = form.cleaned_data['info1']  # your added model fields
    info2 = form.cleaned_data['info2']
    # process info1 and info2 to identify the relevant object(s) needed
    # for the relation
    if( there_is_a_problem):
         form.add_error('info1', 'explain the problem')  
         # the form is now invalid. In a class-based view you can do
         return self.form_invalid( form)
    instance = form.save( commit=False)
    instance.relation =   # what you worked out above
    instance.save()
  • Related