Omar
Omar

Reputation: 35

How can I prefill and save a Django Model record without overwriting the current one?

I have a form that I'd like to prefill with the user's previous input. I used the Form(instance = object) code to do that. However, after the user submits the form, the previous form entry is updated by the new one. I do not want that, rather, I want it to create a different instance so as to keep track of the changes history. Is there a way I can do that while still being able to pre-fill the form?

view.py

from django.shortcuts import render, redirect
from .models import Topic, Entry
from .forms import TopicForm, EntryForm

def edit_entry(request, entry_id):
    entry = Entry.objects.get(id = entry_id)
    topic = entry.topic

    if request.method != 'POST':
        # Initial request; pre-fill for with the current entry.
        form = EntryForm(instance = entry)

    else:
        # POST data submitted.
        form = EntryForm(instance = entry, data = request.POST)
        if form.is_valid():
            form.save()
            return redirect('learning_logs:topic', topic_id = topic.id)

    context = {'entry': entry, 'topic': topic, 'form': form}
    return render(request, 'learning_logs/edit_entry.html', context)

forms.py

from django import forms
from .models import Topic, Entry

class TopicForm(forms.ModelForm):
    class Meta:
        model = Topic
        fields = ['text']
        labels = {'text':''}

class EntryForm(forms.ModelForm):
    class Meta:
        model = Entry
        fields = ['text']
        labels = {'text':''}
        widgets = {'text': forms.Textarea(attrs = {'cols': 80, 'spellcheck':True})}

models.py

from django.db import models
from django.contrib.auth.models import User

class Topic(models.Model):  
    text = models.CharField(max_length = 200)
    date_added = models.DateTimeField(auto_now_add = True)
    owner = models.ForeignKey(User, on_delete = models.CASCADE)

class Entry(models.Model):
    topic = models.ForeignKey(Topic, on_delete = models.CASCADE)
    text = models.TextField()
    date_added = models.DateTimeField(auto_now_add = True)

Upvotes: 2

Views: 209

Answers (1)

willeM_ Van Onsem
willeM_ Van Onsem

Reputation: 476709

You can set the primary key .pk of the entry to None, such that it will create a new record:

from django.shortcuts import render, redirect
from .models import Topic, Entry
from .forms import TopicForm, EntryForm

def edit_entry(request, entry_id):
    entry = Entry.objects.get(id = entry_id)
    topic = entry.topic

    if request.method != 'POST':
        # Initial request; pre-fill for with the current entry.
        form = EntryForm(instance=entry)

    else:
        # POST data submitted.
        entry.pk = None  # ← set .pk entry to None
        form = EntryForm(request.POST, instance=entry)
        if form.is_valid():
            form.save()
            return redirect('learning_logs:topic', topic_id = topic.id)

    context = {'entry': entry, 'topic': topic, 'form': form}
    return render(request, 'learning_logs/edit_entry.html', context)

Upvotes: 2

Related Questions