Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Django Form, how to get further model info for ModelChoiceField

I have 3 models that are related to eachother. A showing has the ‘film’ and ‘screen’ foreignkeys that link to Film and Screen. I’m trying to setup a webpage so that you can view information on a showing that is already setup, and edit it from dropdowns of what films and screens are available.

The problem I have at the moment is that instead of showing the screen numbers, and film titles that can be selected from, my dropdowns are showing ‘Screen Object (4)’ or ‘Film Object (2)’. How do I get that next level of information to show from each object?

My models are:

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

class Film(models.Model):
    ageRatings =[
        ("U", "U"),
        ("PG", "PG"),
        ("12", "12"),
        ("15", "15"),
        ("18", "18"),
    ]

    id = models.AutoField(primary_key=True)
    title = models.CharField(max_length=255)
    length = models.DurationField()
    rating = models.CharField(max_length=3, choices=ageRatings, default="U")
    genre = models.CharField(max_length=50)
    poster_url = models.CharField(max_length=255, default='')
    
    
class Screen(models.Model):
    id = models.AutoField(primary_key=True)
    cinema = models.ForeignKey(Cinema, on_delete=models.CASCADE, related_name='screens')
    screen_number = models.PositiveSmallIntegerField()
    seating_capacity = models.PositiveIntegerField()
    

class Showing(models.Model):
    id = models.AutoField(primary_key=True)
    film = models.ForeignKey(Film, on_delete=models.CASCADE, related_name='showings')
    screen = models.ForeignKey(Screen, on_delete=models.CASCADE, related_name='showings')
    start_time = models.DateTimeField()
    end_time = models.DateTimeField(null=True)
    available_seats = models.IntegerField()
    adult_price = models.FloatField()
    student_price = models.FloatField()
    child_price = models.FloatField()
    
    def save(self, *args, **kwargs):
        self.end_time = self.start_time + self.film.length
        super().save(*args, **kwargs)

    def __str__(self):
        out = self.start_time.strftime("%d %B %Y %I:%M%p")
        out = out + " - " + self.film.title
        print(out)
        return out

My form is:

class ShowingForm(forms.ModelForm):
    screen = forms.ModelChoiceField(queryset=Screen.objects.all().order_by('screen_number'))
    film = forms.ModelChoiceField(queryset=Film.objects.all().order_by('title'))
    class Meta:
        model = Showing
        fields = ['screen', 'film', 'start_time']

My HTML is:

{% extends 'base.html' %}

{% block content %}

<div class="container mt-4">
  <h1>Update Showing</h1>
  <form method="post" action="{% url 'update_showing' showing.id %}">
    {% csrf_token %}
    {% for field in form %}
      <div class="form-group">
        {{ field.label_tag }}
        {{ field }}
      </div>
    {% endfor %}
    <button type="submit" class="btn btn-primary">Update Showing</button>
  </form>
</div>

{% endblock %}

>Solution :

Django searches for the string representation of Screen and Film. You have to define it the same way you did for Showing by implementing the __str__() method. Then this representation is going to replace "Screen Object (4)"

class Film(models.Model):
    ageRatings =[
        ("U", "U"),
        ("PG", "PG"),
        ("12", "12"),
        ("15", "15"),
        ("18", "18"),
    ]

    id = models.AutoField(primary_key=True)
    title = models.CharField(max_length=255)
    length = models.DurationField()
    rating = models.CharField(max_length=3, choices=ageRatings, default="U")
    genre = models.CharField(max_length=50)
    poster_url = models.CharField(max_length=255, default='')

def __str__(self):
    return self.title
    
class Screen(models.Model):
    id = models.AutoField(primary_key=True)
    cinema = models.ForeignKey(Cinema, on_delete=models.CASCADE, related_name='screens')
    screen_number = models.PositiveSmallIntegerField()
    seating_capacity = models.PositiveIntegerField()

def __str__(self):
    return self.screens.name  # adjust this to your the logic of Cinema model
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading