2

I would like to use the values in a choices field in my template. Suppose I had the class:

MY_CHOICES = (
    ('A1', 'The best steak sauce'),
    ('B2', 'Very stealthy'),
    ('C3', 'Missing a P0'))

class MyClass(models.Model):
    my_field = models.CharField(max_length = 2, choices = MY_CHOICES)

and my form is:

<form method="post">
    {% csrf_token %}
    <select>
    {% for m in models.MY_CHOICES %}
        <option>m</option>
    {% endfor %}
    </select>
</form>

What I have here returns an empty select (i.e. one with no options).

I looked at this but couldn't really understand what was going on. Any help would be appreciated, thanks!

Community
  • 1
  • 1
Woody1193
  • 3,389
  • 1
  • 16
  • 45
  • 1
    Have you looked at django's forms, specifically `ModelForm`? https://docs.djangoproject.com/en/1.9/topics/forms/modelforms/#modelform – kaveh Jul 31 '16 at 21:14
  • @kaveh I have indeed looked at it. Unfortunately, the form I created is too complicated to use one of their meta classes as it pulls from two separate models, one of which I don't have control over. – Woody1193 Jul 31 '16 at 21:28

2 Answers2

1

the simplest solution of this problem is, You should create a file forms.py in a same directory where models.py is locaed and write this code into the file:

forms.py

from models import MyClass
from django import forms


class MyForm(forms.ModelForm):

   class Meta:
      model = MyClass

after this pass your form as context in your respective view like this:

views.py

from forms import MyForm # import that created class in previous step
from django.core.context_processors import csrf

def my_view(request):
  context = {}
  context.update(csrf(request))
  context["form"] = MyForm()
  return render(request, "form.html", context)

and at the end use template tag to get the desired output e.g.

form.html

<form method="post">
    {% csrf_token %}
    <select>
     {{ form.as_p }}
    </select>
</form>

May this helps you.

vikas0713
  • 526
  • 6
  • 9
  • Okay, I understand what you're doing here but could you explain why you used the `csrf()` function? – Woody1193 Aug 01 '16 at 17:08
  • this dealts with the csrf attacks refer to the documentation https://docs.djangoproject.com/en/1.9/ref/csrf/, if you are submitting forms using POST method then always use csrf to secure your form submission. – vikas0713 Aug 02 '16 at 07:34
-1

EDIT: Added a new solution since the first was only about a line the author Woody1193 forgot to mention but implemented it already.

NEW:

I have actually had a similar problem and solved it by creating a custom POST function in javascript.

Copied from https://docs.djangoproject.com/en/1.9/ref/csrf/#ajax you can get the cookie with this snippet of code:

// using jQuery
function getCookie(name) {
    var cookieValue = null;
    if (document.cookie && document.cookie !== '') {
        var cookies = document.cookie.split(';');
        for (var i = 0; i < cookies.length; i++) {
            var cookie = jQuery.trim(cookies[i]);
            // Does this cookie string begin with the name we want?
            if (cookie.substring(0, name.length + 1) === (name + '=')) {
                cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
                break;
            }
        }
    }
    return cookieValue;
}
var csrftoken = getCookie('csrftoken');

Having read a solution regarding hidden input forms I was led to go for an analogous approach for tackling the select problem: JavaScript post request like a form submit

Here comes the customized part. I basically used mixed 2 already existent solutions which worked for me. It actually is the second solution in the link above:

// Post to the provided URL with the specified parameters.
function post(path, parameters) {
    var form = $('<form></form>');

    form.attr("method", "post");
    form.attr("action", path);

    var csrf_field.setAttribute("name", 'csrfmiddlewaretoken');
    csrf_field.setAttribute("value", getCookie('csrftoken'));
    form.appendChild(csrf_field);

    $.each(parameters, function(key, value) {
        var field = $('<input></input>');

        field.attr("type", "hidden");
        field.attr("name", key);
        field.attr("value", value);

        form.append(field);
    });

    // The form needs to be a part of the document in
    // order for us to be able to submit it.
    $(document.body).append(form);
    form.submit();
}

OLD:

I solved it by using the csrf_token in the beginning of the form.

Your code would look like:

<form method="post">
  {% crsf_token %}
  <!-- all the good stuff -->
</form>

You can find a better formulated description on how to (hopefully) solve your problem here: https://docs.djangoproject.com/en/1.9/ref/csrf/

Community
  • 1
  • 1
ByteBiter
  • 116
  • 7
  • I am afraid that does not solve my problem. I neglected to include the CSRF in the example. My apologies for that. However, even included the ` – Woody1193 Jul 31 '16 at 21:46