0

I have different model. Choices of Multiselctfield of one model is dependent on another model.So , database has to be queried inside model.py While doing so, this causes problem in migration. (Table doesn't exist error)

class Invigilator(models.Model):
    ---

# this method queries Shift objects and Examroom
def get_invigilator_assignment_list ():
    assignment = []
    shifts = Shift.objects.all()
    for shift in shifts:
        rooms= ExamRoom.objects.all()
        for room in rooms:
            assign = str (shift.shiftName)+ " " +str (room.name) 
            assignment.append (assign)
    return assignment
assignment_choice = []
assign = get_invigilator_assignment_list()
i = 0
for assignm in assign:
    datatuple = (i,assignm)
    assignment_choice.append(datatuple) 
    i= i+1
ASSIGNMENT_CHOICE = tuple(assignment_choice) 

assignment =MultiSelectField (choices = ASSIGNMENT_CHOICE, blank = True, verbose_name="Assignments")
5
  • You're using a wrong approach, you need to use a relationship between the models, not a ChoiceField. In your case a ManyToManyField. It might require a rethink of how you architect your models, but it's the only way. Commented Jan 11, 2019 at 15:29
  • Please elaborate on your suggestion. Commented Jan 11, 2019 at 15:31
  • I don't have the full picture of what you're trying to achieve, what Shift and ExamRoom models are and what an assignment is supposed to represent. So I can't elaborate more than saying that a ManyToMany relationship looks like what you need. Alternatively, create the choices in the form dynamically. But it cannot be done in the model. Your choices are dynamic, they change each time someone adds a Shift or a ExamRoom to the database, so it cannot be set at creation time. Commented Jan 11, 2019 at 15:36
  • Please elaborate more in your question. I suggest adding more information about the Shift, Invigilator and ExamRoom and how are they related. Commented Jan 11, 2019 at 15:42
  • The shift model contains shifts like morning,evening,etc. The exam room model is used for exam rooms like room1 , room2, etc. For the multiselectfield, I need a combination of the two: morning shift room1. So, many to many field is also not applicable. Shift and exam room are independent as they are used separately in other cases. Should I change the architecture of the data models or is there a way to incorporate them? Commented Jan 11, 2019 at 15:51

2 Answers 2

1

You cannot add dynamic choices because they are all stored in the migration files and table info. If Django lets you do that, this means that everytime someone adds a record to those 2 models, a new migration should be created and the db should be changed. You must approach this problem differently.

As far as I know django-smart-selects has a ChainedManyToMany field which can do the trick.

Here is an example from the repo.

from smart_selects.db_fields import ChainedManyToManyField

class Publication(models.Model):
    name = models.CharField(max_length=255)

class Writer(models.Model):
    name = models.CharField(max_length=255)
    publications = models.ManyToManyField('Publication', blank=True, null=True)

class Book(models.Model):
    publication = models.ForeignKey(Publication)
    writer = ChainedManyToManyField(
        Writer,
        chained_field="publication",
        chained_model_field="publications")
    name = models.CharField(max_length=255)
Sign up to request clarification or add additional context in comments.

Comments

0

This cannot be done in the model and doesn't make sense. It's like you're trying to create a column in a table with a certain fixed set of choices (what is MultiSelecField anyway?), but when someone later adds a new row in the Shift or ExamRoom table, the initial column choices have to change again.

You can

  • either make your assignment column a simple CharField and create the choices dynamically when creating the form
  • or you can try to model your relationships differently. For example, since it looks like assignment is a combination of Shift and ExamRoom, I would create a through relationship:
shifts = models.ManyToManyField(Shift, through=Assignment)

class Assignment(Model):
    room = ForeignKey(ExamRoom)
    shift = ForeignKey(Shift)
    invigilator = ForeignKey(Invigilator)

When creating the relationship, you'd have to pick a Shift and a Room which would create the Assignment object. Then you can query things like invigilator.shifts.all() or invigilator.assignment_set.first().room.

7 Comments

I have Shift and ExamRoom which I made admin to select. and for the assignment field, I want Assignments to generate automatically as per Shift and ExamROom and I don't want user to add them manually (by Foreign Key) .If I have 4 shift and 4 classroom (added by Superuser), Now I want 16 choices in Assignment field automatically. By your approach of ForeignKey, I will have to add room,shift also in assignment model which I don't wanna add as I know I will have assignment in all rooms of all shift.
Thank You for answering my question. My teacher told me "I will add ExamRooms,Invigilators,and Shifts.According to those data I provided, there should be choice on assignment .Also an Invigilator can have more than one assignment in a day"
Then take the first approach I suggested: Make assignment a CharField and create the choices in the Django form that you render in your template. But it sounds to me that it will lead to not very good user experience: instead of choosing from n rooms and m shifts, the user now has to select from n x m choices which can become unwieldy. Note that my Assignment model allows for multiple assignments per Invigilator (invigilator.assignment_set.all())
No, total no of shift(n) and total no of examRoom (m) will be provided by college.Invigilators have to choose in which shifts they are available which will be stored in shift (M2M) in invigilator model. and now my task is to display all possible assignments (n*m) in Invigilator assignment filed like checkbox, look at in invigilator available shift and assign them according to that (this will be done by Django Code not manually).
BTW I am newbie to Django and doesn't know all features so . :(
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.