Home > Mobile >  Processing a Django form
Processing a Django form

Time:02-18

I have a problem using Django forms while learning Django and adapting code from a variety of online courses and examples. As a result, the code may be “messy” – but if I can get it to work the way I need, I can improve my coding style later.

I wish to display a template that contains a form. Some of the data displayed in the page rendered in the template is read from one table/model, polls_CC_Questions, and I wish to write data input in the page into a related table, polls_CC_Resp_NoFK.

The models used are:

class CC_Questions(models.Model):
    q_text = models.CharField('Question text', max_length=200)
    C1_Type = models.CharField('Choice 1 Type', max_length=2)
    Choice1_text = models.CharField('Choice 1 text', max_length=100)
    C2_Type = models.CharField('Choice 2 Type', max_length=2)
    Choice2_text = models.CharField('Choice 2 text', max_length=100)
    #
    def __str__(self):
        return self.q_text[:20]


class CC_Resp_NoFK(models.Model):
    Person_ID = models.IntegerField()
    Test_date = models.DateTimeField('date test taken')
    Q_ID = models.IntegerField()
    Response_value = models.IntegerField(default=0,
        validators=[MaxValueValidator(100), MinValueValidator(-100)])
    #
    def __str__(self):
        return self.Person_ID

Now I can display the template containing valid data when I enter the url: http://localhost:8000/polls/p2vote/4/ This is processed in urls.py

app_name = 'polls'
urlpatterns = [
…..
……
    # ex: /polls/p2vote/<q_id>
    path('p2vote/<int:q_id>/', p2_views.p2vote, name='p2vote'),
…..

The views.py entry that is used:

def p2vote(request,q_id): 
    #next line has been copied from CC_quest view to GET Question data
    CC_question = get_object_or_404(CC_Questions, pk=q_id)
    #
    if request.method == 'POST':
        form = VoteForm(request.POST)
        if form.is_valid():
            form.save()
            return redirect('/polls/p2')
    else:
        formV = VoteForm()
    #context = {'form' : formV}
    return render(request, 'pollapp2/vote.html', {'var_name':CC_question,'form' : VoteForm()})

in forms.py

class VoteForm(forms.ModelForm):
    class Meta:
        model = CC_Resp_NoFK
        fields = ['Person_ID', 'Test_date', 'Q_ID','Response_value']

The template launched, uses data from the polls_CC_Questions model/table to create the labels of the input field. This works fine so my displayed page http://localhost:8000/polls/p2vote/5/ Displays data from the CC_Questions table, “carried in the variable varname” what the questions and their choices are. For example, the template displays the contents of {{ var_name.q_text }} and {{ var_name.Choice1_text }} , see below

Also, the page displayed containing the ModelForm is correctly displayed with labels. The template used :

<!-- vote.html based on create.html -->
<!-- 2022-02-17 
Change text on page
Extracted data from CC_Question record passed as varname
-->

{% extends "pollapp2/base.html" %}
<!-- load widget tools to give me more control over layout of form in template -->
{% load widget_tweaks %}
<!-- block Title is the name in the tab -->
{% block title %}Vote on Question{% endblock %}

{% block main %}
<div >
    <div >
        <div >
            <div >
                <h3 >Select one from two choices</h3>
            </div>

            <form method="POST">
            {% csrf_token %}
                <div >
                    <div >
                        <div >
                            <div >
                                <label for="question">Question to answer</label>
                {{ var_name.q_text }}
                            </div>
                        </div>
                    </div>

                    <div >
                        <div >
                            <div >
                                <label for="Choice1_text ">Choice 1</label>

            {{ var_name.Choice1_text }}


                            </div>
                        </div>
                        <div >
                            <div >
                                <label for="option2">Choice 2</label>

            {{ var_name.Choice2_text }}

                            </div>
                        </div>
                       
                    </div>
<!-- Attempt at Input fields follow -->
        <div >
                        <div >
                            <div >
                                <label for="Person_id">Person ID</label>
    {% render_field form.Person_ID rows="1"  %}<br>
                <label for="Test_date">Test Date</label>
    {% render_field form.Test_date rows="1"  %}<br>
         <label for="Q_ID">Question ID</label>
    {% render_field form.Q_ID rows="1"  %}  <br>
                <label for="Response_value">Response value</label>
    {% render_field form.Response_value rows="1"  %}
                            </div>
                        </div>
                </div>
                    <div >
                        <hr />
                        <div >
                            <button type="submit" >Submit</button>
                        </div>
                    </div>
                </div>
            </form>

        </div>
    </div>
</div>
{% endblock %}  

To summarise. All the above “works” in the sense a page is displayed when url : http://localhost:8000/polls/p2vote/X/ is entered in the browser and “X” is the id of the question , extracting data from the model: CC_questions. Also, on the page are input boxes created by the form, VoteForm, that allow data to be entered into table/model CC_Resp_noFK. However, what I want to do is NOT offer Q_ID as an input field in the page, but instead populate it with the value from variable {{ var_name.id }}. I can’t work out whether I need to modify the vote.html template in some way, particularly the line:

<label for="Q_ID">Question ID</label>
    {% render_field form.Q_ID rows="1"  %}   << change this ??

or the view, somewhere around form.save() ??

def p2vote(request,q_id): 
    #next line has been copied from CC_quest view to get Question data
    CC_question = get_object_or_404(CC_Questions, pk=q_id)
    #
    if request.method == 'POST':
        form = VoteForm(request.POST)
        if form.is_valid():
            form.save()  << Somewhere around here ??
            return redirect('/polls/p2') 
    else:
        formV = VoteForm()
        #context = {'form' : formV}
        # return render(request, 'pollapp2/vote.html', context)
        # following return tries to send question record into vote.html template
    return render(request, 'pollapp2/vote.html', {'var_name':CC_question,'form' : VoteForm()})

CodePudding user response:

Step 1: Delete Q_ID from VoteForm.

class VoteForm(forms.ModelForm):
    class Meta:
        model = CC_Resp_NoFK
        fields = ['Person_ID', 'Test_date', 'Response_value']

Step 2: Add Q_ID after check if the form is valid and before save the object.

def p2vote(request,q_id): 
    #next line has been copied from CC_quest view to get Question data
    CC_question = get_object_or_404(CC_Questions, pk=q_id)
    if request.method == 'POST':
        form = VoteForm(request.POST)
        if form.is_valid():
            item = form.save(commit=False)
            item.Q_ID = q_id
            item.save()
            return redirect('/polls/p2') 
  • Related