old_contents: import json
  from django.db import models
  from django.template.loader import render_to_string
  from rest_framework.authtoken.models import Token
  from utils import is_json_string_list, truncate
  
  
  class Problem(models.Model):
      title = models.CharField(max_length=70)
      description = models.TextField(blank=True)
  
      def __unicode__(self):
          return self.title
  
      def user_solutions(self, user):
          attempts = user.attempts.filter(part__problem=self)
          solutions = {}
          for attempt in attempts:
              solutions[attempt.part.id] = attempt.solution
          return solutions
  
      def attempt_file(self, user=None):
          authentication_token = Token.objects.get(user=user) if user else None
          solutions = self.user_solutions(user) if user else {}
          parts = [(part, solutions.get(part.id, '')) for part in self.parts.all()]
          return render_to_string("python/attempt.py", {
              "problem": self,
              "parts": parts,
              "submission_url": "http://localhost:8000/attempt/submit/",
              "authentication_token": authentication_token
          })
  
  
  class Part(models.Model):
      problem = models.ForeignKey(Problem, related_name='parts')
      description = models.TextField(blank=True)
      solution = models.TextField(blank=True)
      validation = models.TextField(blank=True)
      secret = models.TextField(default="[]", validators=[is_json_string_list])
  
      class Meta:
          order_with_respect_to = 'problem'
  
      def __unicode__(self):
          return u'@{0:06d} ({1})'.format(self.pk, truncate(self.description))
  
      def check_secret(self, secret):
          '''
          Checks whether a submitted secret corresponds to the official one.
  
          The function accepts a secret (list of strings) and returns the pair:
          True, None -- if secret matches the official one
          False, None -- if secret has an incorrect length
          False, i -- if secret first differs from the official one at index i
          '''
          official_secret = json.loads(self.secret)
          if len(official_secret) != len(secret):
              return False, None
          for i in range(len(secret)):
              if secret[i] != official_secret[i]:
                  return False, i
          return True, None
  
new_contents: import json
  from django.db import models
  from django.template.loader import render_to_string
  from rest_framework.authtoken.models import Token
  from utils import is_json_string_list, truncate
  
  
  class Problem(models.Model):
      title = models.CharField(max_length=70)
      description = models.TextField(blank=True)
  
      def __unicode__(self):
          return self.title
  
      def user_attempts(self, user):
          return user.attempts.filter(part__problem=self)
  
      def user_solutions(self, user):
          return {attempt.part.id: attempt.solution for attempt in self.user_attempts(user)} 
  
      def attempt_file(self, user=None):
          authentication_token = Token.objects.get(user=user) if user else None
          solutions = self.user_solutions(user) if user else {}
          parts = [(part, solutions.get(part.id, '')) for part in self.parts.all()]
          return render_to_string("python/attempt.py", {
              "problem": self,
              "parts": parts,
              "submission_url": "http://localhost:8000/attempt/submit/",
              "authentication_token": authentication_token
          })
  
  
  class Part(models.Model):
      problem = models.ForeignKey(Problem, related_name='parts')
      description = models.TextField(blank=True)
      solution = models.TextField(blank=True)
      validation = models.TextField(blank=True)
      secret = models.TextField(default="[]", validators=[is_json_string_list])
  
      class Meta:
          order_with_respect_to = 'problem'
  
      def __unicode__(self):
          return u'@{0:06d} ({1})'.format(self.pk, truncate(self.description))
  
      def check_secret(self, secret):
          '''
          Checks whether a submitted secret corresponds to the official one.
  
          The function accepts a secret (list of strings) and returns the pair:
          True, None -- if secret matches the official one
          False, None -- if secret has an incorrect length
          False, i -- if secret first differs from the official one at index i
          '''
          official_secret = json.loads(self.secret)
          if len(official_secret) != len(secret):
              return False, None
          for i in range(len(secret)):
              if secret[i] != official_secret[i]:
                  return False, i
          return True, None
  
subject: Rewrite user_solutions method