AlixL
AlixL

Reputation: 372

Django Form initial Value For Foreignkey Field

I have two django models which are :

class Dataset(models.Model):
    name = models.CharField(max_length = 200)
    description = models.CharField(max_length=1000)
    owner = models.ForeignKey(Profile, null=True, on_delete=models.SET_NULL)
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)


class Source(models.Model):
    name = models.CharField(max_length = 200)
    description = models.CharField(max_length=1000)
    dataset = models.ForeignKey(Dataset, null=True, on_delete=models.SET_NULL)
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)

When saving a Source, I would like to initiate the value of the corresponding Dataset. I tried to initiate the value of my form as suggested here : foreign key as initial value not passed to the ModelForm in django

def create_source(request, dataset_id):

    user = request.user
    dataset = Dataset.objects.get(id=dataset_id)

    form = SourceForm(initial={"dataset" : dataset, })

    if request.method == "POST":
        form = SourceForm(request.POST or None, initial={"dataset" : dataset, })
        if form.is_valid():
            source = form.save()
            # dataset.source_set.add(source) # Only works if I add this line
            return redirect("source", dataset_id=dataset_id, source_id=source.id)

    context = {"form": form}
    return render(request, "sources/source_form.html", context)

The SourceForm:


class SourceForm(ModelForm):

    class Meta:
        model = Source
        fields = "__all__"
        exclude = ["dataset"]

The suggested way does not work. I was able to achieve the desired result by adding the commented line above. It is not a recommended solution since it makes a second call to the database.

Any idea how to give properly the dataset object to the source ?

Upvotes: 1

Views: 710

Answers (1)

Abdul Aziz Barkat
Abdul Aziz Barkat

Reputation: 21797

Passing values in initial for excluded fields does not do anything. Instead what you can do is modify the instance wrapped by the form before saving the it:

def create_source(request, dataset_id):

    user = request.user
    dataset = Dataset.objects.get(id=dataset_id)

    form = SourceForm() # No initial

    if request.method == "POST":
        form = SourceForm(request.POST) # this is a submitted form `request.POST or None` makes no sense use only `request.POST`
        if form.is_valid():
            form.instance.dataset = dataset
            source = form.save()
            return redirect("source", dataset_id=dataset_id, source_id=source.id)

    context = {"form": form}
    return render(request, "sources/source_form.html", context)

Upvotes: 1

Related Questions