简体   繁体   中英

How do I assign instances to models in django?

I'm building a child chore management app, and I've run into a blocker. Here's what I'm trying to do:

  • assign individual kids individual instances of various rules (ie having multiple instances of "wash dishes", so that one kid can complete their version without it being marked as complete for each kid), so I will be able to:
    • only display the rules that are assigned to each kid on their own page (ie kid 1 can have their instances of rules a, b, c displayed, while kid 2 has their instances of rules b, c, d displayed)
  • end goal is to be able to tally up the points each kid has earned

Here's what I have done so far:

  • displaying list of all kids
  • ability to create rules instances
  • displaying all rules instances with every child.

Here are my models:

class Rule(models.Model):
    """
    Model representing a base class for rules. Weight field is how much you want the rule to be worth. The same rule can be applied to multiple kids, and a single kid can be assigned multiple rules.
    """
    name = models.CharField(max_length=50, help_text='Enter rule', default=None)
    weight = models.IntegerField(default=0)
    description = models.TextField(max_length=250, help_text='Enter description of rule')
    completed = models.BooleanField(default=False, help_text='Is this rule completed?')

    def get_absolute_url(self):
        """
        url to gain access to one Rule
        """

        return reverse('rule-detail', args=[str(self.id)])

class RuleInstance(models.Model):
    """
    Model representing instances of rules. Instances should be assigned to kids.
    """
    id = models.UUIDField(primary_key=True, default=uuid.uuid4, help_text='Unique ID for this rule')
    rule = models.ForeignKey(Rule, on_delete=models.SET_NULL, null=True)

class Kid(models.Model):

    name = models.CharField(max_length=20, help_text='Enter kid name', default=None)
    rules = models.ManyToManyField(RuleInstance, help_text='Select a rule to give to this kid')
    # https://docs.djangoproject.com/en/3.0/topics/db/examples/many_to_many/
    points = models.IntegerField(default=0)

    class Meta:
        ordering = ['name']

    # methods
    def __str__(self):
        return f'Name: {self.name}\n Points total: {self.points} \n Rules assigned: {self.rules}'

    def get_absolute_url(self):
        """
        url to gain access to one Kid
        """
    
        return reverse('kid-detail', args=[str(self.id)])

Here are the relevant views:

def index(request):
    """
    view function for site homepage. Stuff below will be subject to change if I don't like how it looks
    """
    kids_list = Kid.objects.all()

    rules_list = Rule.objects.all()

    rule_instance_list = RuleInstance.objects.all()

    context = {
        'kids_list' : kids_list,
        'rules_list' : rules_list,
        'rule_instance_list': rule_instance_list,
    }

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

class KidDetailView(generic.DetailView):
    model = Kid

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)

        context['rule_instance_list'] = RuleInstance.objects.all()

        return context

How should I adjust my models or views to accomplish what I'm after? And is a many to many relationship between the Kid and RuleInstance model the right way to go about this?

  • Since each RuleInstance will be assigned to just one kid, it's better to have a one-to-many relationship.
  • Since each instance of the rule should be marked as "completed" separately, the completed field should go on the instance, not on the rule.

like this:

class RuleInstance(models.Model):
    """
    Model representing instances of rules. Instances should be assigned to kids.
    """
    id = models.UUIDField(primary_key=True, default=uuid.uuid4, help_text='Unique ID for this rule')
    rule = models.ForeignKey(Rule, on_delete=models.SET_NULL, null=True)
    kid = models.ForeignKey(Kid, related_name='rules')
    completed = models.BooleanField(default=False, help_text='Is this rule completed?')

This will add an implicit field to the Kid model called rules .

When you need to create a new rule instance, you'll do something like:

   RuleInstance.objects.create(rule=the_rule, kid=the_kid)

(You'll probably also want a "date" field on the RuleInstance, if chores are regular.)

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