Making an authenticated user's form that can be edited in django

Question:

I am making a medical website, and I wanted to add a feature where the user could add their medical history in a description box. The website renders the main page only when the user has successfully signed in. So what I wanted to do is that they can write their medical history and when in the future they want to change something in it they can edit it in that same description box, as it always shows what you have submitted and is the same for a user. But in my case when I submit it just makes more new descriptions.

#models.py

class History(models.Model):
user = models.ForeignKey(User,on_delete=models.CASCADE)
disc = models.TextField(blank=True)

#views.py

def history(request):

his = History(user = request.user)
form = HistoryForm(request.POST or None, instance=his)
if request.method == "POST":
    
    
    if form.is_valid():
        profile = form.save(commit=False)
        profile.user = request.user
        profile.save()
        
        return redirect('/index')


return render(request, 'history.html', {'form': form})

#urls.py

path('history', views.history, name='history'),

#forms.py

class HistoryForm(ModelForm):
class Meta:
    model = History
    fields = ('disc',)
    
    labels = {
        'disc' : 'History'
    }
    Widget = {
        'disc': forms.Textarea(attrs={'class': 'form-control', 'placeholder': 'Write your medical history here...'}),
    }

Also, (attrs=….) is not working, neither class nor placeholder.

#history.html

    <form class="mx-5 mt-5" method="POST" action="">
    {% csrf_token %} {{form.as_p}}

    <button type="submit" class="btn btn-primary my-3">Submit</button>
  </form>
Asked By: khoprutu

||

Answers:

First, you need to change

his = History(user = request.user)

to

his = History.objects.get(user=request.user)

because what you wrote is not a query, it’s the creation of the History object and that’s why you getting new descriptions.

Example:

    his = History.objects.get(user=request.user)
    form = HistoryForm(request.POST or None, instance=his)

    if request.method == "POST":
        if form.is_valid():
            form.save()
            return redirect('/')

    return render(request, 'history.html', {'form': form})

Also, you can remove commit=False from form.save(commit=False).

Regarding attr, you can write something like this.

class HistoryForm(ModelForm):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.fields['disc'].widget.attrs.update(
            {
                'class': 'form-control', 
                'placeholder': 'Write your medical history here...'
            }
        )

    class Meta:
        model = History
        fields = ('disc',)

        labels = {
            'disc': 'History'
        }
        Widget = {
            'disc': forms.Textarea(),
        } 
Answered By: Milos Bogdanovic
Categories: questions Tags: , , , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.