Search code examples
djangodjango-modelsdjango-viewsdjango-forms

How to capture Data from a column and add it to a dropdown menu for a form to fill another table


Here is my Model. I would like to capture the data in column "Address" then display it in a dropdown menu for a form that i am using to fill another table instead of typing the email address again.

Create your models here.

class Employee(models.Model):
    address = models.EmailField(max_length=100,null=True)
    first_name = models.CharField(max_length=50,null=True)
    sec_name = models.CharField(max_length=50,null=True)       
    department = models.CharField(max_length= 50,null=True)
    company = models.CharField(max_length= 50,null=True)
    date_created = models.DateTimeField(default=timezone.now)
    date_updated = models.DateTimeField(auto_now=True)

def __str__(self):
    return self.first_name + ' - ' + self.department

This is the form i am using to add data to the second model

class SaveCategory(forms.ModelForm):
    name = forms.CharField(max_length="250")
    description = forms.Textarea()
    status = forms.ChoiceField(choices=[('1','Active'),('2','Inactive')])

class Meta:
    model = Category
    fields = ('name','status')

def clean_name(self):
    id = self.instance.id if self.instance.id else 0
    name = self.cleaned_data['name']
    # print(int(id) > 0)

    try:
        if int(id) > 0:
            category = Category.objects.exclude(id=id).get(name = name)
        else:
            category = Category.objects.get(name = name)
    except:
        return name

    raise forms.ValidationError(f"{name} Category Already Exists.")

This is the model i am adding data into.

class Category(models.Model):
    name = models.CharField(max_length=250)
    status = models.CharField(max_length=2, choices=(('1','Active'),('2','Inactive')), default=1)
    date_created = models.DateTimeField(default=timezone.now)
    date_updated = models.DateTimeField(auto_now=True)

    def __str__(self):
        return self.name

Solution

  • You can do this with a ForeignKey [Django-doc], this will also guarantee referential integrity.

    class Category(models.Model):
        name = models.CharField(max_length=250, unique=True)
        status = models.CharField(
            max_length=2, choices=(('1', 'Active'), ('2', 'Inactive')), default=1
        )
        employee = models.ForeignKey(Employee, on_delete=models.PROTECT)
        description = models.TextField()
        date_created = models.DateTimeField(auto_now_add=True)
        date_updated = models.DateTimeField(auto_now=True)
    
        def __str__(self):
            return self.name

    Your form however implements way too much boilerplate logic. By setting unique=True [Django-doc], the form can check if the value is new itself, and by using auto_now_add=True and auto_now=True, the fields are by default non-editable, so will not appear in the form. The form can thus be implemented as:

    class CategoryForm(forms.ModelForm):
        class Meta:
            model = Category
            fields = '__all__'

    and that's __all__.