Elecciones dinámicas en el campo del modelo.

I want my models to have order field, which will contain order of an item among all items of its kind.

Y quiero usar choices dentro de eso IntegerField, which would contain all the numbers of currently existing items in that table.

So it would need to be dynamic choices.

How do I load all existing "order" values of all existing items in a table, and use this list for choices?

preguntado el 23 de diciembre de 12 a las 10:12

Vea este question and check answer given by danihp -

Maybe I would use it if I could in any way understand what it does. -

2 Respuestas

It sounds like you want to build a manager for your model:


from django.db import models

class OrderManager(models.Manager):

    def order_choices(self):
        return [(i, i) for i in OrderModel.objects.values_list('order', flat=True)]

class OrderModel(models.Model): 

    objects = OrderManager()
    order = models.IntegerField()

    class Meta:
        ordering = ['order'] 

    def __unicode__(self):
        return '%i' % self.order


from django import forms

from yourapp.models import OrderModel

class OrderModelForm(forms.ModelForm):
    order = forms.ChoiceField(choices=OrderModel.objects.order_choices())

    class Meta:
        model = OrderModel


from django.contrib import admin

from yourapp.forms import OrderModelForm
from yourapp.models import OrderModel

class OrderModelAdmin(admin.ModelAdmin):

    form = OrderModelForm

admin.site.register(OrderModel, OrderModelAdmin)


Managers are use to make general model queries without having an instance of a model object. If you don't understand the concept of managers, you can still refactor the code out of the manager class, stick it somewhere else and import that function across your code. Managers allow you to abstract custom general queryset that you can reuse. See more details https://docs.djangoproject.com/en/dev/topics/db/managers/

The code without the manager will look like

views.py or some other file

from app.models import OrderModel

def order_choices():
    return [(i, i) for i in OrderModel.objects.values_list('order', flat=True)]

From anywhere in your code, if you want to reuse the above multiple times:

from app.views import oder_choices


Opuesto a:

from app.models import OderModel


If you only want to use the above once, you can leave it in the forms.py as shown in the other answer. It's really up to you on how you want to refactor your code.

Respondido el 24 de diciembre de 12 a las 05:12

I understand forms.py and admin.py, but why would (in this solution) I need a custom manager? Won't I achieve what is desired by just using custom form? If I want to order items by the "order" value, I could do that without the manager, can't I? - tonino.j

I thought you wanted a way to find that list from the model as from your previous comment which explains the use of the manager. You can re-clarify your question if its original meaning has changed so that we can answer it properly. - Thierry Lam

Yes, I do want to load/create CHOICES list from all currently existing models in the database. However, I just need this info in the select box in the form. (or in the possible choices in the model itself, so it validates properly on model level, not form level - even better). But if I achieve this with custom form - so I get desired values in my select box, then what is the meaning of the manager? Please, elaborate your solution a bit, I am a bit lost. I upvoted it, but I don't fully understand it. - tonino.j

I think this can be done without any manager. I understand managers to a degree, but I can simply load the select choices with list comprehension: CHOICES = [(item.order, item.order) for item in MyModel.objects.all()] - tonino.j

Thats why I asked why I would need manager when I already need to create custom forms.py - tonino.j

Dont add the choices directly to the model, add them to a form represnting the model later, by overriding the field with a set of choices.

than, do something like:

class MyForm(..):
    myfield_order_field = IntegerField(choices = [(i,i) for range(MyModel.objects.count)])
    class Meta():
        model = MyModel

if you want to use it in the admin, add to your Admin Class:

class MyModelAdmin(admin.ModelAdmin):

    form = MyForm

it will override this field in the admin too.

Respondido el 23 de diciembre de 12 a las 13:12

I understand, but I want the select field to be available in the admin, too. So doing it properly in the model is the way to go, I think. - tonino.j

But is there a way to call Model.objects.all() form the model definition? Is is possible to get that list from model? I'll accept this, if I dont find other way. - tonino.j

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.