简体   繁体   中英

How to display objects in a drop down list (django)?

python=2.7, django=1.11.13

In my html I am not able to display my condition choices from my models.py When filling the form, the user is not able to choose a condition because they are not displayed.

models.py

class Books(models.Model):
    book_name = models.CharField(max_length=100)
    book_condition = models.ForeignKey('Condition')

    def __unicode__(self):
        return self.book_name


class Condition(models.Model):
    NEW = 'new'
    USED = 'used'
    COLLECTIBLE = 'collectible'
    CONDITION_CHOICES = (
        (NEW, 'New'),
        (USED, 'Used'),
        (COLLECTIBLE, 'collectible'),
    )
    book = models.ForeignKey(Books)
    condition = models.CharField(max_length=10, choices=CONDITION_CHOICES)

    def __unicode__(self):
        return self.condition

views.py

def add_book(request):
    if request.method == 'GET':
        context = {
            'form': BookForm()
        }

    if request.method == 'POST':
        form = BookForm(request.POST)
        if form.is_valid():
             form.save()
        context = {
            'form': form,
        }

    return render(request, 'add_book_form.html', context=context)

add_book_form.html

{% extends 'base.html' %}
{% block body %}

<h3>Add Book </h3>
<form action="" method="post">
    {% csrf_token %}
    {{ form}}

    <br/>
    <input class="button" type="submit" value="Submit"/>
</form>

{% endblock %}

And this is my form, I'm not sure what I am missing.

form

from django.forms import ModelForm
from .models import Books, Condition


class BookForm(ModelForm):
    class Meta:
        model = Books
        fields = '__all__'


class ConditionForm(ModelForm):
    class Meta:
        model = Condition
        fields = '__all__'

Try to use Django widgets . For example:

class BookForm(forms.Form):
categories = (('Adventure', 'Action'),
              ('Terror', 'Thriller'),
              ('Business', 'War'),)
description = forms.CharField(max_length=9)
category = forms.ChoiceField(required=False,
                             widget=forms.Select,
                             choices=categories)

The form you're passing to the view is a BookForm, the BookForm contains a ForeignKey field to the Condition model, so the options in the select will be instances of the Condition model.

You would need to preemptively create the Condition model instances, via the admin interface or the shell, and then you could see the conditions on the select, but that won't help, because your Condition instance needs to be associated to a Book, and that makes me think your software is badly designed.

Let me propose a solution:

class Book(models.Model):
    """
    This model stores the book name and the condition in the same
    table, no need to create a new table for this data.
    """
    NEW = 0
    USED = 1
    COLLECTIBLE = 2
    CONDITION_CHOICES = (
        (NEW, 'New'),
        (USED, 'Used'),
        (COLLECTIBLE, 'Collectible'),
    )
    name = models.CharField(max_length=100)
    condition = models.SmallIntegerField(choices=CONDITION_CHOICES)

    def __unicode__(self):
        return "{0} ({1})".format(self.book_name, self.condition)

class BookForm(ModelForm):
    class Meta:
        model = Book
        fields = '__all__'

Now the conditions are saved as an integer (like it would be if you used foreign keys) and your software is easier to understand and develop.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM