cssidy
cssidy

Reputation: 405

Django multiple-choice field of options in database

I am designing a model, view and template for my news aggregation app. I want the template to offer the user a multiple-choice field form with options from the database. How do I design this in my model?

I was reading the Django documentation about ManyToManyField (the one with journalists and articles) but I don't think that is quite the right relationship because in my case, "articles" can exist without a journalist and journalist without an article.

I have Users. I have Streams. Streams is a collection of news sites a user can sign up to follow and see aggregated headline snippets, such as from CNN,Twitter, Google News, etc etc. A Stream can exist with no Users. A Stream can have many Users. A User can have no Streams, in fact all user accounts start in my app with no Streams until they choose one. A User can have many Streams.

In the template, I want to create a form with the list of all the Stream options in the database (this will likely change as I ad more options in the future). When a User selects a Stream, it will be added to their dashboard view. They can add and delete Streams. However, there is only 1 Twitter, 1 Google News, etc source. I can't use the typical choices option in the User model, I want it to be "dynamic" and pull straight from the Streams database.

This is what I have now but I know it's not right:

streams/models.py

from django.db import models
from django.contrib.auth.models import User


class Stream(models.Model):
    user = models.ManyToManyField(User, blank=True, null=True)
    name = models.CharField(max_length=30)

user/models.py

from django.db import models


class User(models.Model):
     name = models.CharField(max_length=30)

     '''''
     #TODO: make this dynamic, streams is pulling from Streams model
        streams = (
            ('Google News'),
            ('Yahoo News'),
            ('Twitter'),
            ('CNN'),
            ('New York Times'),
            ('NBC News'),
            ('Huffington Post')
        )
        stream_choices = models.CharField(max_length=9, choices=streams)


     '''''

Upvotes: 1

Views: 3297

Answers (2)

Jarvis Cochrane
Jarvis Cochrane

Reputation: 101

The ManyToManyField already implicitly creates the 'intermediary table' described in the accepted answer. As per the documentation:

Behind the scenes, Django creates an intermediary join table to represent the many-to-many relationship.

You can pass a callable to the choices field of the ChoicesField which you display to the user, allowing the list of available choices to be determined dynamically when the form is generated.

The list of valid choices in the User<->Stream relationship is already constrained by the relationship, so there's no benefit in specifying the available choices on the model field.

Upvotes: 0

Borut
Borut

Reputation: 3364

Just add one model for list of streams and another model for user selected streams

class Stream(models.Model):
    name = models.CharField(max_length=50)

class UserStream(models.Model):
    user = models.ForeignKey(User)
    name = models.ForeignKey(Stream)

That's it. Insert possible streams to Stream model and user selected streams to UserStream model.

Upvotes: 1

Related Questions