We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Log change in Challenge and Challenge Phase model when file fields are updated
__Problem__

We need a way to figure out if the `evaluation_script`field value is changed for Challenge Model or not. Same goes for `test_annotation` field in ChallengePhase Model.

__Please be more clear__ ?

When ever a model is saved, its saved function is called. So this task involves figuring out a way in save model to detect if the model is updated or added. If the model is updated, then further it should be figured out whether the `evaluation_script` is changed for Challenge model or not.

If `evaluation_script` of Challenge model is changed, then simply print a message stating the change. This print statement will later on act as a logging statement in case we need to debug something.

The above requested thing goes same for `test_annotation` field of ChallengePhase model.

__Why__ ?

Submission worker when starts loads all `evaluation_script` and `test_annotation` file in advance. In case if the Challenge Host updates any of the file, there is no way to communicate this to the worker

__Impact__ ?

It actually guarantees that whenever any submission is evaluated, it is evaluated against the write set of parameters.

__How__ ?

As of now, I think it can be done via following ways

* Either overriding the save method of each model and adding a hook over there to check if the instance is being updated or added. May be there is a flag or something which tells whether the instance is added or updated

* Either by [signals](https://docs.djangoproject.com/en/1.10/topics/signals/). Reason I am asking to use signal because we need to carry out the same set of action for more than one models(presently _Challenge_ and _ChallengePhase_). Doing it by signal will help us achieve more modularized code.

* Your suggestion ??

__TakeAways__

About how django model is saved, how signal works, and a brief intro about RabbitMQ and submission worker

Also I will prefer that __before coding__, its better to __discuss__ the approach over here only, so that we can get an idea and update if something is not right.

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `apps/base/models.py`
Content:
```
1 from __future__ import unicode_literals
2 
3 from django.db import models
4 
5 
6 class TimeStampedModel(models.Model):
7     """
8     An abstract base class model that provides self-managed `created_at` and
9     `modified_at` fields.
10     """
11     created_at = models.DateTimeField(auto_now_add=True)
12     modified_at = models.DateTimeField(auto_now=True)
13 
14     class Meta:
15         abstract = True
16         app_label = 'base'
17
```

Path: `apps/challenges/models.py`
Content:
```
1 from __future__ import unicode_literals
2 
3 from django.contrib.auth.models import User
4 from django.utils import timezone
5 from django.contrib.postgres.fields import JSONField
6 from django.db import models
7 
8 from base.models import (TimeStampedModel, )
9 from base.utils import RandomFileName
10 from participants.models import (ParticipantTeam, )
11 
12 
13 class Challenge(TimeStampedModel):
14 
15     """Model representing a hosted Challenge"""
16     title = models.CharField(max_length=100)
17     short_description = models.TextField(null=True, blank=True)
18     description = models.TextField(null=True, blank=True)
19     terms_and_conditions = models.TextField(null=True, blank=True)
20     submission_guidelines = models.TextField(null=True, blank=True)
21     evaluation_details = models.TextField(null=True, blank=True)
22     image = models.ImageField(
23         upload_to='logos', null=True, blank=True, verbose_name="Logo")
24     start_date = models.DateTimeField(
25         null=True, blank=True, verbose_name="Start Date (UTC)")
26     end_date = models.DateTimeField(
27         null=True, blank=True, verbose_name="End Date (UTC)")
28     creator = models.ForeignKey(
29         'hosts.ChallengeHostTeam', related_name='challenge_creator')
30     published = models.BooleanField(
31         default=False, verbose_name="Publicly Available")
32     enable_forum = models.BooleanField(default=True)
33     anonymous_leaderboard = models.BooleanField(default=False)
34     participant_teams = models.ManyToManyField(ParticipantTeam, blank=True)
35     is_disabled = models.BooleanField(default=False)
36     evaluation_script = models.FileField(
37         default=False, upload_to=RandomFileName("evaluation_scripts"))  # should be zip format
38     approved_by_admin = models.BooleanField(
39         default=False, verbose_name="Approved By Admin")
40 
41     class Meta:
42         app_label = 'challenges'
43         db_table = 'challenge'
44 
45     def __unicode__(self):
46         """Returns the title of Challenge"""
47         return self.title
48 
49     def get_image_url(self):
50         """Returns the url of logo of Challenge"""
51         if self.image:
52             return self.image.url
53         return None
54 
55     def get_evaluation_script_path(self):
56         """Returns the path of evaluation script"""
57         if self.evaluation_script:
58             return self.evaluation_script.url
59         return None
60 
61     def get_start_date(self):
62         """Returns the start date of Challenge"""
63         return self.start_date
64 
65     def get_end_date(self):
66         """Returns the end date of Challenge"""
67         return self.end_date
68 
69     @property
70     def is_active(self):
71         """Returns if the challenge is active or not"""
72         if self.start_date < timezone.now() and self.end_date > timezone.now():
73             return True
74         return False
75 
76 
77 class DatasetSplit(TimeStampedModel):
78     name = models.CharField(max_length=100)
79     codename = models.CharField(max_length=100, unique=True)
80 
81     def __unicode__(self):
82         return self.name
83 
84     class Meta:
85         app_label = 'challenges'
86         db_table = 'dataset_split'
87 
88 
89 class ChallengePhase(TimeStampedModel):
90 
91     """Model representing a Challenge Phase"""
92     name = models.CharField(max_length=100)
93     description = models.TextField()
94     leaderboard_public = models.BooleanField(default=False)
95     start_date = models.DateTimeField(
96         null=True, blank=True, verbose_name="Start Date (UTC)")
97     end_date = models.DateTimeField(
98         null=True, blank=True, verbose_name="End Date (UTC)")
99     challenge = models.ForeignKey('Challenge')
100     is_public = models.BooleanField(default=False)
101     is_submission_public = models.BooleanField(default=False)
102     test_annotation = models.FileField(upload_to=RandomFileName("test_annotations"), default=False)
103     max_submissions_per_day = models.PositiveIntegerField(default=100000)
104     max_submissions = models.PositiveIntegerField(default=100000)
105     codename = models.CharField(max_length=100, default="Phase Code Name")
106     dataset_split = models.ManyToManyField(DatasetSplit, blank=True, through='ChallengePhaseSplit')
107 
108     class Meta:
109         app_label = 'challenges'
110         db_table = 'challenge_phase'
111         unique_together = (('codename', 'challenge'),)
112 
113     def __unicode__(self):
114         """Returns the name of Phase"""
115         return self.name
116 
117     def get_start_date(self):
118         """Returns the start date of Phase"""
119         return self.start_date
120 
121     def get_end_date(self):
122         """Returns the end date of Challenge"""
123         return self.end_date
124 
125     @property
126     def is_active(self):
127         """Returns if the challenge is active or not"""
128         if self.start_date < timezone.now() and self.end_date > timezone.now():
129             return True
130         return False
131 
132 
133 class Leaderboard(TimeStampedModel):
134 
135     schema = JSONField()
136 
137     def __unicode__(self):
138         return '{}'.format(self.id)
139 
140     class Meta:
141         app_label = 'challenges'
142         db_table = 'leaderboard'
143 
144 
145 class ChallengePhaseSplit(TimeStampedModel):
146 
147     # visibility options
148     HOST = 1
149     OWNER_AND_HOST = 2
150     PUBLIC = 3
151 
152     VISIBILITY_OPTIONS = (
153         (HOST, 'host'),
154         (OWNER_AND_HOST, 'owner and host'),
155         (PUBLIC, 'public'),
156     )
157 
158     challenge_phase = models.ForeignKey('ChallengePhase')
159     dataset_split = models.ForeignKey('DatasetSplit')
160     leaderboard = models.ForeignKey('Leaderboard')
161     visibility = models.PositiveSmallIntegerField(
162         choices=VISIBILITY_OPTIONS,
163         default=PUBLIC
164     )
165 
166     def __unicode__(self):
167         return '{0} : {1}'.format(self.challenge_phase.name, self.dataset_split.name)
168 
169     class Meta:
170         app_label = 'challenges'
171         db_table = 'challenge_phase_split'
172 
173 
174 class LeaderboardData(TimeStampedModel):
175 
176     challenge_phase_split = models.ForeignKey('ChallengePhaseSplit')
177     submission = models.ForeignKey('jobs.Submission')
178     leaderboard = models.ForeignKey('Leaderboard')
179     result = JSONField()
180 
181     def __unicode__(self):
182         return '{0} : {1}'.format(self.challenge_phase_split, self.submission)
183 
184     class Meta:
185         app_label = 'challenges'
186         db_table = 'leaderboard_data'
187 
188 
189 class ChallengeConfiguration(TimeStampedModel):
190     """
191     Model to store zip file for challenge creation.
192     """
193     user = models.ForeignKey(User)
194     challenge = models.OneToOneField(Challenge, null=True, blank=True)
195     zip_configuration = models.FileField(upload_to=RandomFileName('zip_configuration_files/challenge_zip'))
196     is_created = models.BooleanField(default=False)
197     stdout_file = models.FileField(upload_to=RandomFileName('zip_configuration_files/challenge_zip'),
198                                    null=True, blank=True)
199     stderr_file = models.FileField(upload_to=RandomFileName('zip_configuration_files/challenge_zip'),
200                                    null=True, blank=True)
201 
202     class Meta:
203         app_label = 'challenges'
204         db_table = 'challenge_zip_configuration'
205
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/apps/base/models.py b/apps/base/models.py
--- a/apps/base/models.py
+++ b/apps/base/models.py
@@ -1,7 +1,12 @@
 from __future__ import unicode_literals
 
+import logging
+
 from django.db import models
 
+# Get an instance of a logger
+logger = logging.getLogger(__name__)
+
 
 class TimeStampedModel(models.Model):
     """
@@ -14,3 +19,24 @@
     class Meta:
         abstract = True
         app_label = 'base'
+
+
+def model_field_name(field_name, *args, **kwargs):
+    """
+    The decorator is used to pass model field names to create_post_model_field function for logging change.
+    """
+    def model_field_name_decorator(f, *args, **kwargs):
+        def model_field_name_wrapper(sender, instance, **kwargs):
+            f(sender, instance, field_name=field_name, **kwargs)
+        return model_field_name_wrapper
+    return model_field_name_decorator
+
+
+def create_post_model_field(sender, instance, field_name, **kwargs):
+    """
+    When any model field value changes, it is used to log the change.
+    """
+    if getattr(instance, '_original_{}'.format(field_name)) is False:
+        logger.info('{} for {} is added first time !'.format(field_name, instance.pk))
+    else:
+        logger.info('{} for {} changed !'.format(field_name, instance.pk))
diff --git a/apps/challenges/models.py b/apps/challenges/models.py
--- a/apps/challenges/models.py
+++ b/apps/challenges/models.py
@@ -4,8 +4,9 @@
 from django.utils import timezone
 from django.contrib.postgres.fields import JSONField
 from django.db import models
+from django.db.models import signals
 
-from base.models import (TimeStampedModel, )
+from base.models import (TimeStampedModel, model_field_name, create_post_model_field, )
 from base.utils import RandomFileName
 from participants.models import (ParticipantTeam, )
 
@@ -13,6 +14,11 @@
 class Challenge(TimeStampedModel):
 
     """Model representing a hosted Challenge"""
+
+    def __init__(self, *args, **kwargs):
+        super(Challenge, self).__init__(*args, **kwargs)
+        self._original_evaluation_script = self.evaluation_script
+
     title = models.CharField(max_length=100)
     short_description = models.TextField(null=True, blank=True)
     description = models.TextField(null=True, blank=True)
@@ -74,6 +80,10 @@
         return False
 
 
+signals.post_save.connect(model_field_name(field_name='evaluation_script')(create_post_model_field),
+                          sender=Challenge, weak=False)
+
+
 class DatasetSplit(TimeStampedModel):
     name = models.CharField(max_length=100)
     codename = models.CharField(max_length=100, unique=True)
@@ -89,6 +99,10 @@
 class ChallengePhase(TimeStampedModel):
 
     """Model representing a Challenge Phase"""
+    def __init__(self, *args, **kwargs):
+        super(ChallengePhase, self).__init__(*args, **kwargs)
+        self._original_test_annotation = self.test_annotation
+
     name = models.CharField(max_length=100)
     description = models.TextField()
     leaderboard_public = models.BooleanField(default=False)
@@ -130,6 +144,10 @@
         return False
 
 
+signals.post_save.connect(model_field_name(field_name='test_annotation')(create_post_model_field),
+                          sender=ChallengePhase, weak=False)
+
+
 class Leaderboard(TimeStampedModel):
 
     schema = JSONField()

{"golden_diff": "diff --git a/apps/base/models.py b/apps/base/models.py\n--- a/apps/base/models.py\n+++ b/apps/base/models.py\n@@ -1,7 +1,12 @@\n from __future__ import unicode_literals\n \n+import logging\n+\n from django.db import models\n \n+# Get an instance of a logger\n+logger = logging.getLogger(__name__)\n+\n \n class TimeStampedModel(models.Model):\n     \"\"\"\n@@ -14,3 +19,24 @@\n     class Meta:\n         abstract = True\n         app_label = 'base'\n+\n+\n+def model_field_name(field_name, *args, **kwargs):\n+    \"\"\"\n+    The decorator is used to pass model field names to create_post_model_field function for logging change.\n+    \"\"\"\n+    def model_field_name_decorator(f, *args, **kwargs):\n+        def model_field_name_wrapper(sender, instance, **kwargs):\n+            f(sender, instance, field_name=field_name, **kwargs)\n+        return model_field_name_wrapper\n+    return model_field_name_decorator\n+\n+\n+def create_post_model_field(sender, instance, field_name, **kwargs):\n+    \"\"\"\n+    When any model field value changes, it is used to log the change.\n+    \"\"\"\n+    if getattr(instance, '_original_{}'.format(field_name)) is False:\n+        logger.info('{} for {} is added first time !'.format(field_name, instance.pk))\n+    else:\n+        logger.info('{} for {} changed !'.format(field_name, instance.pk))\ndiff --git a/apps/challenges/models.py b/apps/challenges/models.py\n--- a/apps/challenges/models.py\n+++ b/apps/challenges/models.py\n@@ -4,8 +4,9 @@\n from django.utils import timezone\n from django.contrib.postgres.fields import JSONField\n from django.db import models\n+from django.db.models import signals\n \n-from base.models import (TimeStampedModel, )\n+from base.models import (TimeStampedModel, model_field_name, create_post_model_field, )\n from base.utils import RandomFileName\n from participants.models import (ParticipantTeam, )\n \n@@ -13,6 +14,11 @@\n class Challenge(TimeStampedModel):\n \n     \"\"\"Model representing a hosted Challenge\"\"\"\n+\n+    def __init__(self, *args, **kwargs):\n+        super(Challenge, self).__init__(*args, **kwargs)\n+        self._original_evaluation_script = self.evaluation_script\n+\n     title = models.CharField(max_length=100)\n     short_description = models.TextField(null=True, blank=True)\n     description = models.TextField(null=True, blank=True)\n@@ -74,6 +80,10 @@\n         return False\n \n \n+signals.post_save.connect(model_field_name(field_name='evaluation_script')(create_post_model_field),\n+                          sender=Challenge, weak=False)\n+\n+\n class DatasetSplit(TimeStampedModel):\n     name = models.CharField(max_length=100)\n     codename = models.CharField(max_length=100, unique=True)\n@@ -89,6 +99,10 @@\n class ChallengePhase(TimeStampedModel):\n \n     \"\"\"Model representing a Challenge Phase\"\"\"\n+    def __init__(self, *args, **kwargs):\n+        super(ChallengePhase, self).__init__(*args, **kwargs)\n+        self._original_test_annotation = self.test_annotation\n+\n     name = models.CharField(max_length=100)\n     description = models.TextField()\n     leaderboard_public = models.BooleanField(default=False)\n@@ -130,6 +144,10 @@\n         return False\n \n \n+signals.post_save.connect(model_field_name(field_name='test_annotation')(create_post_model_field),\n+                          sender=ChallengePhase, weak=False)\n+\n+\n class Leaderboard(TimeStampedModel):\n \n     schema = JSONField()\n", "issue": "Log change in Challenge and Challenge Phase model when file fields are updated\n__Problem__\r\n\r\nWe need a way to figure out if the `evaluation_script`field value is changed for Challenge Model or not. Same goes for `test_annotation` field in ChallengePhase Model.\r\n\r\n__Please be more clear__ ?\r\n\r\nWhen ever a model is saved, its saved function is called. So this task involves figuring out a way in save model to detect if the model is updated or added. If the model is updated, then further it should be figured out whether the `evaluation_script` is changed for Challenge model or not.\r\n\r\nIf `evaluation_script` of Challenge model is changed, then simply print a message stating the change. This print statement will later on act as a logging statement in case we need to debug something.\r\n\r\nThe above requested thing goes same for `test_annotation` field of ChallengePhase model.\r\n\r\n__Why__ ?\r\n\r\nSubmission worker when starts loads all `evaluation_script` and `test_annotation` file in advance. In case if the Challenge Host updates any of the file, there is no way to communicate this to the worker\r\n\r\n__Impact__ ?\r\n\r\nIt actually guarantees that whenever any submission is evaluated, it is evaluated against the write set of parameters.\r\n\r\n__How__ ?\r\n\r\nAs of now, I think it can be done via following ways\r\n\r\n* Either overriding the save method of each model and adding a hook over there to check if the instance is being updated or added. May be there is a flag or something which tells whether the instance is added or updated\r\n\r\n* Either by [signals](https://docs.djangoproject.com/en/1.10/topics/signals/). Reason I am asking to use signal because we need to carry out the same set of action for more than one models(presently _Challenge_ and _ChallengePhase_). Doing it by signal will help us achieve more modularized code.\r\n\r\n* Your suggestion ??\r\n\r\n__TakeAways__\r\n\r\nAbout how django model is saved, how signal works, and a brief intro about RabbitMQ and submission worker\r\n\r\nAlso I will prefer that __before coding__, its better to __discuss__ the approach over here only, so that we can get an idea and update if something is not right.\n", "before_files": [{"content": "from __future__ import unicode_literals\n\nfrom django.db import models\n\n\nclass TimeStampedModel(models.Model):\n    \"\"\"\n    An abstract base class model that provides self-managed `created_at` and\n    `modified_at` fields.\n    \"\"\"\n    created_at = models.DateTimeField(auto_now_add=True)\n    modified_at = models.DateTimeField(auto_now=True)\n\n    class Meta:\n        abstract = True\n        app_label = 'base'\n", "path": "apps/base/models.py"}, {"content": "from __future__ import unicode_literals\n\nfrom django.contrib.auth.models import User\nfrom django.utils import timezone\nfrom django.contrib.postgres.fields import JSONField\nfrom django.db import models\n\nfrom base.models import (TimeStampedModel, )\nfrom base.utils import RandomFileName\nfrom participants.models import (ParticipantTeam, )\n\n\nclass Challenge(TimeStampedModel):\n\n    \"\"\"Model representing a hosted Challenge\"\"\"\n    title = models.CharField(max_length=100)\n    short_description = models.TextField(null=True, blank=True)\n    description = models.TextField(null=True, blank=True)\n    terms_and_conditions = models.TextField(null=True, blank=True)\n    submission_guidelines = models.TextField(null=True, blank=True)\n    evaluation_details = models.TextField(null=True, blank=True)\n    image = models.ImageField(\n        upload_to='logos', null=True, blank=True, verbose_name=\"Logo\")\n    start_date = models.DateTimeField(\n        null=True, blank=True, verbose_name=\"Start Date (UTC)\")\n    end_date = models.DateTimeField(\n        null=True, blank=True, verbose_name=\"End Date (UTC)\")\n    creator = models.ForeignKey(\n        'hosts.ChallengeHostTeam', related_name='challenge_creator')\n    published = models.BooleanField(\n        default=False, verbose_name=\"Publicly Available\")\n    enable_forum = models.BooleanField(default=True)\n    anonymous_leaderboard = models.BooleanField(default=False)\n    participant_teams = models.ManyToManyField(ParticipantTeam, blank=True)\n    is_disabled = models.BooleanField(default=False)\n    evaluation_script = models.FileField(\n        default=False, upload_to=RandomFileName(\"evaluation_scripts\"))  # should be zip format\n    approved_by_admin = models.BooleanField(\n        default=False, verbose_name=\"Approved By Admin\")\n\n    class Meta:\n        app_label = 'challenges'\n        db_table = 'challenge'\n\n    def __unicode__(self):\n        \"\"\"Returns the title of Challenge\"\"\"\n        return self.title\n\n    def get_image_url(self):\n        \"\"\"Returns the url of logo of Challenge\"\"\"\n        if self.image:\n            return self.image.url\n        return None\n\n    def get_evaluation_script_path(self):\n        \"\"\"Returns the path of evaluation script\"\"\"\n        if self.evaluation_script:\n            return self.evaluation_script.url\n        return None\n\n    def get_start_date(self):\n        \"\"\"Returns the start date of Challenge\"\"\"\n        return self.start_date\n\n    def get_end_date(self):\n        \"\"\"Returns the end date of Challenge\"\"\"\n        return self.end_date\n\n    @property\n    def is_active(self):\n        \"\"\"Returns if the challenge is active or not\"\"\"\n        if self.start_date < timezone.now() and self.end_date > timezone.now():\n            return True\n        return False\n\n\nclass DatasetSplit(TimeStampedModel):\n    name = models.CharField(max_length=100)\n    codename = models.CharField(max_length=100, unique=True)\n\n    def __unicode__(self):\n        return self.name\n\n    class Meta:\n        app_label = 'challenges'\n        db_table = 'dataset_split'\n\n\nclass ChallengePhase(TimeStampedModel):\n\n    \"\"\"Model representing a Challenge Phase\"\"\"\n    name = models.CharField(max_length=100)\n    description = models.TextField()\n    leaderboard_public = models.BooleanField(default=False)\n    start_date = models.DateTimeField(\n        null=True, blank=True, verbose_name=\"Start Date (UTC)\")\n    end_date = models.DateTimeField(\n        null=True, blank=True, verbose_name=\"End Date (UTC)\")\n    challenge = models.ForeignKey('Challenge')\n    is_public = models.BooleanField(default=False)\n    is_submission_public = models.BooleanField(default=False)\n    test_annotation = models.FileField(upload_to=RandomFileName(\"test_annotations\"), default=False)\n    max_submissions_per_day = models.PositiveIntegerField(default=100000)\n    max_submissions = models.PositiveIntegerField(default=100000)\n    codename = models.CharField(max_length=100, default=\"Phase Code Name\")\n    dataset_split = models.ManyToManyField(DatasetSplit, blank=True, through='ChallengePhaseSplit')\n\n    class Meta:\n        app_label = 'challenges'\n        db_table = 'challenge_phase'\n        unique_together = (('codename', 'challenge'),)\n\n    def __unicode__(self):\n        \"\"\"Returns the name of Phase\"\"\"\n        return self.name\n\n    def get_start_date(self):\n        \"\"\"Returns the start date of Phase\"\"\"\n        return self.start_date\n\n    def get_end_date(self):\n        \"\"\"Returns the end date of Challenge\"\"\"\n        return self.end_date\n\n    @property\n    def is_active(self):\n        \"\"\"Returns if the challenge is active or not\"\"\"\n        if self.start_date < timezone.now() and self.end_date > timezone.now():\n            return True\n        return False\n\n\nclass Leaderboard(TimeStampedModel):\n\n    schema = JSONField()\n\n    def __unicode__(self):\n        return '{}'.format(self.id)\n\n    class Meta:\n        app_label = 'challenges'\n        db_table = 'leaderboard'\n\n\nclass ChallengePhaseSplit(TimeStampedModel):\n\n    # visibility options\n    HOST = 1\n    OWNER_AND_HOST = 2\n    PUBLIC = 3\n\n    VISIBILITY_OPTIONS = (\n        (HOST, 'host'),\n        (OWNER_AND_HOST, 'owner and host'),\n        (PUBLIC, 'public'),\n    )\n\n    challenge_phase = models.ForeignKey('ChallengePhase')\n    dataset_split = models.ForeignKey('DatasetSplit')\n    leaderboard = models.ForeignKey('Leaderboard')\n    visibility = models.PositiveSmallIntegerField(\n        choices=VISIBILITY_OPTIONS,\n        default=PUBLIC\n    )\n\n    def __unicode__(self):\n        return '{0} : {1}'.format(self.challenge_phase.name, self.dataset_split.name)\n\n    class Meta:\n        app_label = 'challenges'\n        db_table = 'challenge_phase_split'\n\n\nclass LeaderboardData(TimeStampedModel):\n\n    challenge_phase_split = models.ForeignKey('ChallengePhaseSplit')\n    submission = models.ForeignKey('jobs.Submission')\n    leaderboard = models.ForeignKey('Leaderboard')\n    result = JSONField()\n\n    def __unicode__(self):\n        return '{0} : {1}'.format(self.challenge_phase_split, self.submission)\n\n    class Meta:\n        app_label = 'challenges'\n        db_table = 'leaderboard_data'\n\n\nclass ChallengeConfiguration(TimeStampedModel):\n    \"\"\"\n    Model to store zip file for challenge creation.\n    \"\"\"\n    user = models.ForeignKey(User)\n    challenge = models.OneToOneField(Challenge, null=True, blank=True)\n    zip_configuration = models.FileField(upload_to=RandomFileName('zip_configuration_files/challenge_zip'))\n    is_created = models.BooleanField(default=False)\n    stdout_file = models.FileField(upload_to=RandomFileName('zip_configuration_files/challenge_zip'),\n                                   null=True, blank=True)\n    stderr_file = models.FileField(upload_to=RandomFileName('zip_configuration_files/challenge_zip'),\n                                   null=True, blank=True)\n\n    class Meta:\n        app_label = 'challenges'\n        db_table = 'challenge_zip_configuration'\n", "path": "apps/challenges/models.py"}], "after_files": [{"content": "from __future__ import unicode_literals\n\nimport logging\n\nfrom django.db import models\n\n# Get an instance of a logger\nlogger = logging.getLogger(__name__)\n\n\nclass TimeStampedModel(models.Model):\n    \"\"\"\n    An abstract base class model that provides self-managed `created_at` and\n    `modified_at` fields.\n    \"\"\"\n    created_at = models.DateTimeField(auto_now_add=True)\n    modified_at = models.DateTimeField(auto_now=True)\n\n    class Meta:\n        abstract = True\n        app_label = 'base'\n\n\ndef model_field_name(field_name, *args, **kwargs):\n    \"\"\"\n    The decorator is used to pass model field names to create_post_model_field function for logging change.\n    \"\"\"\n    def model_field_name_decorator(f, *args, **kwargs):\n        def model_field_name_wrapper(sender, instance, **kwargs):\n            f(sender, instance, field_name=field_name, **kwargs)\n        return model_field_name_wrapper\n    return model_field_name_decorator\n\n\ndef create_post_model_field(sender, instance, field_name, **kwargs):\n    \"\"\"\n    When any model field value changes, it is used to log the change.\n    \"\"\"\n    if getattr(instance, '_original_{}'.format(field_name)) is False:\n        logger.info('{} for {} is added first time !'.format(field_name, instance.pk))\n    else:\n        logger.info('{} for {} changed !'.format(field_name, instance.pk))\n", "path": "apps/base/models.py"}, {"content": "from __future__ import unicode_literals\n\nfrom django.contrib.auth.models import User\nfrom django.utils import timezone\nfrom django.contrib.postgres.fields import JSONField\nfrom django.db import models\nfrom django.db.models import signals\n\nfrom base.models import (TimeStampedModel, model_field_name, create_post_model_field, )\nfrom base.utils import RandomFileName\nfrom participants.models import (ParticipantTeam, )\n\n\nclass Challenge(TimeStampedModel):\n\n    \"\"\"Model representing a hosted Challenge\"\"\"\n\n    def __init__(self, *args, **kwargs):\n        super(Challenge, self).__init__(*args, **kwargs)\n        self._original_evaluation_script = self.evaluation_script\n\n    title = models.CharField(max_length=100)\n    short_description = models.TextField(null=True, blank=True)\n    description = models.TextField(null=True, blank=True)\n    terms_and_conditions = models.TextField(null=True, blank=True)\n    submission_guidelines = models.TextField(null=True, blank=True)\n    evaluation_details = models.TextField(null=True, blank=True)\n    image = models.ImageField(\n        upload_to='logos', null=True, blank=True, verbose_name=\"Logo\")\n    start_date = models.DateTimeField(\n        null=True, blank=True, verbose_name=\"Start Date (UTC)\")\n    end_date = models.DateTimeField(\n        null=True, blank=True, verbose_name=\"End Date (UTC)\")\n    creator = models.ForeignKey(\n        'hosts.ChallengeHostTeam', related_name='challenge_creator')\n    published = models.BooleanField(\n        default=False, verbose_name=\"Publicly Available\")\n    enable_forum = models.BooleanField(default=True)\n    anonymous_leaderboard = models.BooleanField(default=False)\n    participant_teams = models.ManyToManyField(ParticipantTeam, blank=True)\n    is_disabled = models.BooleanField(default=False)\n    evaluation_script = models.FileField(\n        default=False, upload_to=RandomFileName(\"evaluation_scripts\"))  # should be zip format\n    approved_by_admin = models.BooleanField(\n        default=False, verbose_name=\"Approved By Admin\")\n\n    class Meta:\n        app_label = 'challenges'\n        db_table = 'challenge'\n\n    def __unicode__(self):\n        \"\"\"Returns the title of Challenge\"\"\"\n        return self.title\n\n    def get_image_url(self):\n        \"\"\"Returns the url of logo of Challenge\"\"\"\n        if self.image:\n            return self.image.url\n        return None\n\n    def get_evaluation_script_path(self):\n        \"\"\"Returns the path of evaluation script\"\"\"\n        if self.evaluation_script:\n            return self.evaluation_script.url\n        return None\n\n    def get_start_date(self):\n        \"\"\"Returns the start date of Challenge\"\"\"\n        return self.start_date\n\n    def get_end_date(self):\n        \"\"\"Returns the end date of Challenge\"\"\"\n        return self.end_date\n\n    @property\n    def is_active(self):\n        \"\"\"Returns if the challenge is active or not\"\"\"\n        if self.start_date < timezone.now() and self.end_date > timezone.now():\n            return True\n        return False\n\n\nsignals.post_save.connect(model_field_name(field_name='evaluation_script')(create_post_model_field),\n                          sender=Challenge, weak=False)\n\n\nclass DatasetSplit(TimeStampedModel):\n    name = models.CharField(max_length=100)\n    codename = models.CharField(max_length=100, unique=True)\n\n    def __unicode__(self):\n        return self.name\n\n    class Meta:\n        app_label = 'challenges'\n        db_table = 'dataset_split'\n\n\nclass ChallengePhase(TimeStampedModel):\n\n    \"\"\"Model representing a Challenge Phase\"\"\"\n    def __init__(self, *args, **kwargs):\n        super(ChallengePhase, self).__init__(*args, **kwargs)\n        self._original_test_annotation = self.test_annotation\n\n    name = models.CharField(max_length=100)\n    description = models.TextField()\n    leaderboard_public = models.BooleanField(default=False)\n    start_date = models.DateTimeField(\n        null=True, blank=True, verbose_name=\"Start Date (UTC)\")\n    end_date = models.DateTimeField(\n        null=True, blank=True, verbose_name=\"End Date (UTC)\")\n    challenge = models.ForeignKey('Challenge')\n    is_public = models.BooleanField(default=False)\n    is_submission_public = models.BooleanField(default=False)\n    test_annotation = models.FileField(upload_to=RandomFileName(\"test_annotations\"), default=False)\n    max_submissions_per_day = models.PositiveIntegerField(default=100000)\n    max_submissions = models.PositiveIntegerField(default=100000)\n    codename = models.CharField(max_length=100, default=\"Phase Code Name\")\n    dataset_split = models.ManyToManyField(DatasetSplit, blank=True, through='ChallengePhaseSplit')\n\n    class Meta:\n        app_label = 'challenges'\n        db_table = 'challenge_phase'\n        unique_together = (('codename', 'challenge'),)\n\n    def __unicode__(self):\n        \"\"\"Returns the name of Phase\"\"\"\n        return self.name\n\n    def get_start_date(self):\n        \"\"\"Returns the start date of Phase\"\"\"\n        return self.start_date\n\n    def get_end_date(self):\n        \"\"\"Returns the end date of Challenge\"\"\"\n        return self.end_date\n\n    @property\n    def is_active(self):\n        \"\"\"Returns if the challenge is active or not\"\"\"\n        if self.start_date < timezone.now() and self.end_date > timezone.now():\n            return True\n        return False\n\n\nsignals.post_save.connect(model_field_name(field_name='test_annotation')(create_post_model_field),\n                          sender=ChallengePhase, weak=False)\n\n\nclass Leaderboard(TimeStampedModel):\n\n    schema = JSONField()\n\n    def __unicode__(self):\n        return '{}'.format(self.id)\n\n    class Meta:\n        app_label = 'challenges'\n        db_table = 'leaderboard'\n\n\nclass ChallengePhaseSplit(TimeStampedModel):\n\n    # visibility options\n    HOST = 1\n    OWNER_AND_HOST = 2\n    PUBLIC = 3\n\n    VISIBILITY_OPTIONS = (\n        (HOST, 'host'),\n        (OWNER_AND_HOST, 'owner and host'),\n        (PUBLIC, 'public'),\n    )\n\n    challenge_phase = models.ForeignKey('ChallengePhase')\n    dataset_split = models.ForeignKey('DatasetSplit')\n    leaderboard = models.ForeignKey('Leaderboard')\n    visibility = models.PositiveSmallIntegerField(\n        choices=VISIBILITY_OPTIONS,\n        default=PUBLIC\n    )\n\n    def __unicode__(self):\n        return '{0} : {1}'.format(self.challenge_phase.name, self.dataset_split.name)\n\n    class Meta:\n        app_label = 'challenges'\n        db_table = 'challenge_phase_split'\n\n\nclass LeaderboardData(TimeStampedModel):\n\n    challenge_phase_split = models.ForeignKey('ChallengePhaseSplit')\n    submission = models.ForeignKey('jobs.Submission')\n    leaderboard = models.ForeignKey('Leaderboard')\n    result = JSONField()\n\n    def __unicode__(self):\n        return '{0} : {1}'.format(self.challenge_phase_split, self.submission)\n\n    class Meta:\n        app_label = 'challenges'\n        db_table = 'leaderboard_data'\n\n\nclass ChallengeConfiguration(TimeStampedModel):\n    \"\"\"\n    Model to store zip file for challenge creation.\n    \"\"\"\n    user = models.ForeignKey(User)\n    challenge = models.OneToOneField(Challenge, null=True, blank=True)\n    zip_configuration = models.FileField(upload_to=RandomFileName('zip_configuration_files/challenge_zip'))\n    is_created = models.BooleanField(default=False)\n    stdout_file = models.FileField(upload_to=RandomFileName('zip_configuration_files/challenge_zip'),\n                                   null=True, blank=True)\n    stderr_file = models.FileField(upload_to=RandomFileName('zip_configuration_files/challenge_zip'),\n                                   null=True, blank=True)\n\n    class Meta:\n        app_label = 'challenges'\n        db_table = 'challenge_zip_configuration'\n", "path": "apps/challenges/models.py"}]}