orzel
orzel

Reputation: 15

Django edit form

I'm using Django v1.11.8 and Python 2.7.6

I got some question about edit form. Can someone explain me how to write correct edit form in Django? I'm working whole day and still got some problems... I saw lot of examples in Internet but i still do something wrong.

My ModelForm looks like this:

class UpdateVoteForm(ModelForm):
    class Meta:
        model = Vote
        fields = ['question', 'ans_a', 'ans_b', 'ans_c', 'ans_d', 'ans_e', 'ans_f', 'type', 'council', 'user', 'created_date', 'group']

view function:

def update_vote_from(request, pk):
    vote_inst = get_object_or_404(Vote, pk = pk)
    if request.method == 'POST':

        form = UpdateVoteForm(request.POST, instance=vote_inst)
        if form.is_valid():
            #vote_inst = form.save(commit=False)
            #vote_inst.created_date = datetime.date.today()
            form.save()

            return HttpResponseRedirect(reverse('voting-list'))

    else:
        form = UpdateVoteForm()

    return render(request, 'votes-form.html', {'form': form, 'vote_inst': vote_inst})

urls:

urlpatterns = [
    url(r'^$', views.index, name='index'),
    url(r'^votersList/$', views.VotersView.as_view(), name='voters-list'), 
    url(r'^vote/create/$', views.add_vote_from, name='vote-create'),
    url(r'^vote/(?P<pk>\d+)/edit/$', views.update_vote_from, name='vote-update'),     
]

and template:

{% extends "base_generic.html" %}

{% block content %}

<div class="containter">
<form action="" method="post">
    {% csrf_token %}

<label for="user">Właściciel: </label>
    <select id="user" name="user">
        {% for user in vote_inst.user.all %}
            <option value="{{ user }}"{% if vote_inst.user == user %} selected{% endif %}>{{ user }}</option>
        {% endfor %}
    </select>

    <label for="user">Kto: </label>
    <input id="user" type="text" name="user" value="{{ vote_inst.user }}">

    <label for="question">Pytanie: </label>
    <textarea id="question" name="question" style="height:70px" value="{{ vote_inst.question.value }}"></textarea>

    <label for="ans_a">Odpowiedź A: </label>
    <input id="ans_a" type="text" name="ans_a" placeholder="Wpisz odpowiedź A" value="{{ vote_inst.ans_a }}">

    <label for="ans_b">Odpowiedź B: </label>
    <input id="ans_b" type="text" name="ans_b" value="{{ vote_inst.ans_b }}">

    <label for="ans_c">Odpowiedź C: </label>
    <input id="ans_c" type="text" name="ans_c" value="{{ vote_inst.ans_c }}">

    <label for="ans_d">Odpowiedź D: </label>
    <input id="ans_d" type="text" name="ans_d" value="{{ vote_inst.ans_d }}">

    <label for="ans_e">Odpowiedź E: </label>
    <input id="ans_e" type="text" name="ans_e" value="{{ vote_inst.ans_e }}">

    <label for="ans_f">Odpowiedź F: </label>
    <input id="ans_f" type="text" name="ans_f" value="{{ vote_inst.ans_f }}">

    <label for="type">Typ głosowania: </label>
    <select id="type" name="type">
        {% for x,y in vote_inst.type_choices %}
            <option value="{{ x }}"{% if vote_inst.type == x %} selected{% endif %}>{{ y }}</option>
        {% endfor %}
    </select>    
    <input type="submit" value="Zatwierdź" />


</form>
</div>

{% endblock %}

Model:

class Vote(models.Model):

    STATUS_INACTIVE = 0
    STATUS_ACTIVE_NOW = 1
    STATUS_FINISHED = 2
    STATUS_DELETED = 3

    TYPE_UNDECLARED = 0
    TYPE_PUBLIC = 1
    TYPE_NONPUBLIC = 2

    NO_RESULT = 0
    RESULT_A = 1
    RESULT_B = 2
    RESULT_C = 3
    RESULT_D = 4
    RESULT_E = 5
    RESULT_F = 6

    user = models.ForeignKey(User, on_delete=models.CASCADE)
    group = models.ForeignKey(Group, on_delete=models.CASCADE)
    voted_list = models.ManyToManyField(
        Voter,
        through='Voted',
        #through_fields=('Vote', 'Voter'),
    )
    council = models.ForeignKey(Council, on_delete=models.CASCADE)
    type_choices = (
        (TYPE_PUBLIC, 'Jawne'),
        (TYPE_NONPUBLIC, 'Niejawne'),
    )
    type = models.IntegerField(choices=type_choices, default=TYPE_PUBLIC)
    status_choices = (
        (STATUS_INACTIVE, 'Nieaktywne'),
        (STATUS_ACTIVE_NOW, 'Aktywne'),
        (STATUS_FINISHED, 'Zakończone'),
    )
    status = models.IntegerField(choices=status_choices, default=STATUS_INACTIVE)
    question = models.TextField()
    ans_a = models.TextField(null=True, blank=True)
    ans_b = models.TextField(null=True, blank=True)
    ans_c = models.TextField(null=True, blank=True)
    ans_d = models.TextField(null=True, blank=True)
    ans_e = models.TextField(null=True, blank=True)
    ans_f = models.TextField(null=True, blank=True)
    result_choices = (
        (NO_RESULT, 'No result'),
        (RESULT_A, 'A'),
        (RESULT_B, 'B'),
        (RESULT_C, 'C'),
        (RESULT_D, 'D'),
        (RESULT_E, 'E'),
        (RESULT_F, 'F'),
    )
    result = models.IntegerField(choices=result_choices, default=NO_RESULT)
    begin_date = models.DateTimeField(null=True, blank=True)
    finish_date = models.DateTimeField(null=True, blank=True)
    created_date = models.DateTimeField(default=timezone.now)

    def get_status(self):
        return self.status_choices[self.status][1]

    def get_absolute_url(self):
        return reverse('vote-update', args=[str(self.id)])

    def __unicode__(self):
        return "%s" % self.question

class User(models.Model):
    STATUS_INACTIVE = 0
    STATUS_ACTIVE = 1
    STATUS_DELETED = 2

    PRIVILIGES_UNDECLARED = 0
    PRIVILIGES_ADMIN = 1
    PRIVILIGES_MANAGER = 2
    PRIVILIGES_REPORTER = 3

    forename = models.CharField(max_length=50)
    name = models.CharField(max_length=50)
    login = models.CharField(max_length=30)
    password = models.CharField(max_length=50)
    last_login = models.DateTimeField(null=True, blank=True)
    priviliges_choices = (
        (PRIVILIGES_UNDECLARED ,'Undeclared'),
        (PRIVILIGES_ADMIN      ,'Administrator'),
        (PRIVILIGES_MANAGER    ,'Voting Manager'),
        (PRIVILIGES_REPORTER   ,'Reporter'),
    )
    priviligies = models.IntegerField(choices=priviliges_choices, default=PRIVILIGES_UNDECLARED)
    status_choices = (
        (STATUS_INACTIVE ,'Inactive'),
        (STATUS_ACTIVE   ,'Active'),
        (STATUS_DELETED  ,'Deleted'),
    )
    status = models.IntegerField(choices=status_choices, default=STATUS_INACTIVE)

    def get_absolute_url(self):
        return reverse('user-detail', args=[str(self.id)])

    def __unicode__(self):
        return "%s: %s %s" % (self.login, self.forename, self.name)

There is few things:

  1. text area is not filled while trying to edit some instance of Vote
  2. Select list is empty, I think my "for" loop is bad.
  3. Submit button do nothing... because of form.is_valid() returns 0.
  4. I think I'm doing wrong not using Django users model, what you think?
  5. If you see any bad coding behavior let me know too.
  6. Should I stay with Python 2.7 and Django 1.11? I feel better with Py2.7 but if it cause more problems in future I can change it.

Upvotes: 0

Views: 5849

Answers (1)

Daniel Roseman
Daniel Roseman

Reputation: 599490

You shouldn't be doing any of this. Most of your problems are caused by trying to output the form fields yourself, instead of letting Django do it. Remove all of that and either just use {{ form.as_p }}, or iterate through the form fields and output each one:

{{ form.user.label_tag }}
{{ form.user }}
{{ form.user.errors }}

Upvotes: 2

Related Questions