We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
ddionrails.base.mixins uses eval for questionable purposes
### Subject of the issue

eval executes arbitrary python code and is used by the modelMixin to get attributes of objects:

https://github.com/ddionrails/ddionrails/blob/0a9b1d2d490ad7fc9ce90d5e6f68bfaf06c06bf3/ddionrails/base/mixins.py#L94-L106

https://github.com/ddionrails/ddionrails/blob/0a9b1d2d490ad7fc9ce90d5e6f68bfaf06c06bf3/ddionrails/base/mixins.py#L134-L143

https://github.com/ddionrails/ddionrails/blob/0a9b1d2d490ad7fc9ce90d5e6f68bfaf06c06bf3/ddionrails/base/mixins.py#L134-L155

Dedicated functionality should be used to do this instead, i.e. getattr().
This might have to be done recursively since the functions seem to have been used to get attributes over an arbitrary number of relations, e.g. object.objectAttribute.attribute or object.attribute.

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `ddionrails/base/mixins.py`
Content:
```
1 """
2 Mixins for DDI on Rails.
3 """
4 from django import forms
5 
6 from config.helpers import render_markdown
7 
8 
9 class ModelMixin:
10     """
11     Default mixins for all classes in DDI on Rails.
12 
13     Requires two definition in the ``DOR`` class:
14 
15     * io_fields: Fields that are used for the default form and in the default dict.
16     * id_fields: Fields that are used for the get_or_create default method.
17 
18     Example:
19 
20     ::
21 
22         from django.db import models
23         from ddionrails.mixins import ModelMixin
24 
25         class Test(models.Model, ModelMixin):
26 
27             name = models.CharField(max_length=255, unique=True)
28 
29             class DOR:
30                 id_fields = ["name"]
31                 io_fields = ["name"]
32 
33     The default value for DOR is:
34 
35     ::
36 
37         class DOR:
38             id_fields = ["name"]
39             io_fields = ["name", "label", "description"]
40 
41     The ``id_fields`` are also use to construct a default string identifier.
42     It is therefore recommended, to order them from the most general to the
43     most specific one.
44 
45     """
46 
47     class DOR:
48         id_fields = ["name"]
49         io_fields = ["name", "label", "description"]
50 
51     @classmethod
52     def get_or_create(cls, x, lower_strings=True):
53         """
54         Default for the get_or_create based on a dict.
55 
56         The method uses only relevant identifiers based on ``DOR.id_fields``.
57 
58         By default, all strings are set to lower case (option ``lower_strings``).
59         """
60         definition = {key: x[key] for key in cls.DOR.id_fields}
61         for key, value in definition.items():
62             if value.__class__ == str and lower_strings:
63                 definition[key] = value.lower()
64         return cls.objects.get_or_create(**definition)[0]
65 
66     @classmethod
67     def get(cls, x):
68         """
69         Default for the get_or_create based on a dict.
70 
71         The method uses only relevant identifiers based on ``DOR.id_fields``.
72         """
73         try:
74             definition = {key: x[key] for key in cls.DOR.id_fields}
75             result = cls.objects.get(**definition)
76         except cls.DoesNotExist:
77             result = None
78         return result
79 
80     @classmethod
81     def default_form(cls):
82         """
83         Creates a default form for all attributes defined in ``DOR.io_fields``.
84         """
85 
86         class DefaultForm(forms.ModelForm):
87             class Meta:
88                 model = cls
89                 fields = cls.DOR.io_fields
90 
91         return DefaultForm
92 
93     def to_dict(self):
94         """
95         Uses the ``DOR.io_fields`` attribute to generate a default
96         dict object for the current instance.
97         """
98         default_dict = {}
99         for field_name in self.DOR.io_fields:
100             field = eval("self.%s" % field_name)
101             try:
102                 default_dict[field_name] = field.pk
103             except AttributeError:
104                 default_dict[field_name] = field
105         return default_dict
106 
107     def title(self):
108         """
109         Default for the title. It first looks for a valid label, next for a
110         valid name, and otherwise returns an empty string.
111         """
112         try:
113             name = self.name
114         except AttributeError:
115             name = ""
116         try:
117             label = self.label
118         except AttributeError:
119             label = ""
120         return name if label == "" else label
121 
122     def html_description(self):
123         """
124         Uses the ddionrails Markdown parser (ddionrails.helpers) to render
125         the description into HTML.
126         """
127         try:
128             html = render_markdown(self.description)
129         except AttributeError:
130             html = ""
131         return html
132 
133     def get_attribute(self, attribute, default=None):
134         """
135         Example::
136 
137             study_id = variable.get_attribute("self.dataset.study.id")
138         """
139         try:
140             return eval(attribute)
141         except AttributeError:
142             return default
143 
144     def string_id(self):
145         a = []
146         for field_name in self.DOR.id_fields:
147             field = eval("self.%s" % field_name)
148             try:
149                 s = field.string_id()
150             except AttributeError:
151                 s = str(field)
152             a.append(s)
153         a = "/".join(a)
154         return a
155 
156     def __str__(self):
157         return self.string_id()
158 
159 
160 class AdminMixin:
161     """ A mixin for ModelAdmins to query related models via methods """
162 
163     @staticmethod
164     def study_name(obj):
165         """ Return the name of the related study """
166         try:
167             return obj.study.name
168         except AttributeError:
169             return None
170 
171     @staticmethod
172     def period_name(obj):
173         """ Return the name of the related period """
174         try:
175             return obj.period.name
176         except AttributeError:
177             return None
178 
179     @staticmethod
180     def analysis_unit_name(obj):
181         """ Return the name of the related analysis_unit """
182         try:
183             return obj.analysis_unit.name
184         except AttributeError:
185             return None
186 
187     @staticmethod
188     def dataset_name(obj):
189         """ Return the name of the related dataset """
190         try:
191             return obj.dataset.name
192         except AttributeError:
193             return None
194 
195     @staticmethod
196     def dataset_study_name(obj):
197         """ Return the name of the related dataset.study """
198         try:
199             return obj.dataset.study.name
200         except AttributeError:
201             return None
202 
203     @staticmethod
204     def instrument_name(obj):
205         """ Return the name of the related instrument """
206         try:
207             return obj.instrument.name
208         except AttributeError:
209             return None
210 
211     @staticmethod
212     def instrument_study_name(obj):
213         """ Return the name of the related instrument.study """
214         try:
215             return obj.instrument.study.name
216         except AttributeError:
217             return None
218 
219     @staticmethod
220     def basket_name(obj):
221         """ Return the name of the related basket """
222         try:
223             return obj.basket.name
224         except AttributeError:
225             return None
226 
227     @staticmethod
228     def basket_study_name(obj):
229         """ Return the name of the related basket.study """
230         try:
231             return obj.basket.study.name
232         except AttributeError:
233             return None
234 
235     @staticmethod
236     def user_name(obj):
237         """ Return the name of the related basket.user """
238         try:
239             return obj.basket.user.username
240         except AttributeError:
241             return None
242
```
--- 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/ddionrails/base/mixins.py b/ddionrails/base/mixins.py
--- a/ddionrails/base/mixins.py
+++ b/ddionrails/base/mixins.py
@@ -1,6 +1,9 @@
-"""
-Mixins for DDI on Rails.
-"""
+# -*- coding: utf-8 -*-
+
+""" Mixins for ddionrails.base app """
+
+from typing import Dict
+
 from django import forms
 
 from config.helpers import render_markdown
@@ -64,14 +67,14 @@
         return cls.objects.get_or_create(**definition)[0]
 
     @classmethod
-    def get(cls, x):
+    def get(cls, parameters: Dict):
         """
         Default for the get_or_create based on a dict.
 
         The method uses only relevant identifiers based on ``DOR.id_fields``.
         """
         try:
-            definition = {key: x[key] for key in cls.DOR.id_fields}
+            definition = {key: parameters[key] for key in cls.DOR.id_fields}
             result = cls.objects.get(**definition)
         except cls.DoesNotExist:
             result = None
@@ -90,19 +93,19 @@
 
         return DefaultForm
 
-    def to_dict(self):
+    def to_dict(self) -> Dict:
         """
         Uses the ``DOR.io_fields`` attribute to generate a default
         dict object for the current instance.
         """
-        default_dict = {}
-        for field_name in self.DOR.io_fields:
-            field = eval("self.%s" % field_name)
+        dictionary = dict()
+        for field in self.DOR.io_fields:
+            value = getattr(self, field)
             try:
-                default_dict[field_name] = field.pk
+                dictionary[field] = value.pk
             except AttributeError:
-                default_dict[field_name] = field
-        return default_dict
+                dictionary[field] = value
+        return dictionary
 
     def title(self):
         """
@@ -130,31 +133,16 @@
             html = ""
         return html
 
-    def get_attribute(self, attribute, default=None):
-        """
-        Example::
-
-            study_id = variable.get_attribute("self.dataset.study.id")
-        """
-        try:
-            return eval(attribute)
-        except AttributeError:
-            return default
-
-    def string_id(self):
-        a = []
-        for field_name in self.DOR.id_fields:
-            field = eval("self.%s" % field_name)
+    def __str__(self):
+        """ Returns a string reprensentation of the instance, using DOR.id_fields """
+        result = []
+        for field in self.DOR.id_fields:
+            value = getattr(self, field)
             try:
-                s = field.string_id()
+                result.append(value.string_id())
             except AttributeError:
-                s = str(field)
-            a.append(s)
-        a = "/".join(a)
-        return a
-
-    def __str__(self):
-        return self.string_id()
+                result.append(str(value))
+        return "/".join(result)
 
 
 class AdminMixin:

{"golden_diff": "diff --git a/ddionrails/base/mixins.py b/ddionrails/base/mixins.py\n--- a/ddionrails/base/mixins.py\n+++ b/ddionrails/base/mixins.py\n@@ -1,6 +1,9 @@\n-\"\"\"\n-Mixins for DDI on Rails.\n-\"\"\"\n+# -*- coding: utf-8 -*-\n+\n+\"\"\" Mixins for ddionrails.base app \"\"\"\n+\n+from typing import Dict\n+\n from django import forms\n \n from config.helpers import render_markdown\n@@ -64,14 +67,14 @@\n         return cls.objects.get_or_create(**definition)[0]\n \n     @classmethod\n-    def get(cls, x):\n+    def get(cls, parameters: Dict):\n         \"\"\"\n         Default for the get_or_create based on a dict.\n \n         The method uses only relevant identifiers based on ``DOR.id_fields``.\n         \"\"\"\n         try:\n-            definition = {key: x[key] for key in cls.DOR.id_fields}\n+            definition = {key: parameters[key] for key in cls.DOR.id_fields}\n             result = cls.objects.get(**definition)\n         except cls.DoesNotExist:\n             result = None\n@@ -90,19 +93,19 @@\n \n         return DefaultForm\n \n-    def to_dict(self):\n+    def to_dict(self) -> Dict:\n         \"\"\"\n         Uses the ``DOR.io_fields`` attribute to generate a default\n         dict object for the current instance.\n         \"\"\"\n-        default_dict = {}\n-        for field_name in self.DOR.io_fields:\n-            field = eval(\"self.%s\" % field_name)\n+        dictionary = dict()\n+        for field in self.DOR.io_fields:\n+            value = getattr(self, field)\n             try:\n-                default_dict[field_name] = field.pk\n+                dictionary[field] = value.pk\n             except AttributeError:\n-                default_dict[field_name] = field\n-        return default_dict\n+                dictionary[field] = value\n+        return dictionary\n \n     def title(self):\n         \"\"\"\n@@ -130,31 +133,16 @@\n             html = \"\"\n         return html\n \n-    def get_attribute(self, attribute, default=None):\n-        \"\"\"\n-        Example::\n-\n-            study_id = variable.get_attribute(\"self.dataset.study.id\")\n-        \"\"\"\n-        try:\n-            return eval(attribute)\n-        except AttributeError:\n-            return default\n-\n-    def string_id(self):\n-        a = []\n-        for field_name in self.DOR.id_fields:\n-            field = eval(\"self.%s\" % field_name)\n+    def __str__(self):\n+        \"\"\" Returns a string reprensentation of the instance, using DOR.id_fields \"\"\"\n+        result = []\n+        for field in self.DOR.id_fields:\n+            value = getattr(self, field)\n             try:\n-                s = field.string_id()\n+                result.append(value.string_id())\n             except AttributeError:\n-                s = str(field)\n-            a.append(s)\n-        a = \"/\".join(a)\n-        return a\n-\n-    def __str__(self):\n-        return self.string_id()\n+                result.append(str(value))\n+        return \"/\".join(result)\n \n \n class AdminMixin:\n", "issue": "ddionrails.base.mixins uses eval for questionable purposes\n### Subject of the issue\r\n\r\neval executes arbitrary python code and is used by the modelMixin to get attributes of objects:\r\n\r\nhttps://github.com/ddionrails/ddionrails/blob/0a9b1d2d490ad7fc9ce90d5e6f68bfaf06c06bf3/ddionrails/base/mixins.py#L94-L106\r\n\r\nhttps://github.com/ddionrails/ddionrails/blob/0a9b1d2d490ad7fc9ce90d5e6f68bfaf06c06bf3/ddionrails/base/mixins.py#L134-L143\r\n\r\nhttps://github.com/ddionrails/ddionrails/blob/0a9b1d2d490ad7fc9ce90d5e6f68bfaf06c06bf3/ddionrails/base/mixins.py#L134-L155\r\n\r\nDedicated functionality should be used to do this instead, i.e. getattr().\r\nThis might have to be done recursively since the functions seem to have been used to get attributes over an arbitrary number of relations, e.g. object.objectAttribute.attribute or object.attribute.\n", "before_files": [{"content": "\"\"\"\nMixins for DDI on Rails.\n\"\"\"\nfrom django import forms\n\nfrom config.helpers import render_markdown\n\n\nclass ModelMixin:\n    \"\"\"\n    Default mixins for all classes in DDI on Rails.\n\n    Requires two definition in the ``DOR`` class:\n\n    * io_fields: Fields that are used for the default form and in the default dict.\n    * id_fields: Fields that are used for the get_or_create default method.\n\n    Example:\n\n    ::\n\n        from django.db import models\n        from ddionrails.mixins import ModelMixin\n\n        class Test(models.Model, ModelMixin):\n\n            name = models.CharField(max_length=255, unique=True)\n\n            class DOR:\n                id_fields = [\"name\"]\n                io_fields = [\"name\"]\n\n    The default value for DOR is:\n\n    ::\n\n        class DOR:\n            id_fields = [\"name\"]\n            io_fields = [\"name\", \"label\", \"description\"]\n\n    The ``id_fields`` are also use to construct a default string identifier.\n    It is therefore recommended, to order them from the most general to the\n    most specific one.\n\n    \"\"\"\n\n    class DOR:\n        id_fields = [\"name\"]\n        io_fields = [\"name\", \"label\", \"description\"]\n\n    @classmethod\n    def get_or_create(cls, x, lower_strings=True):\n        \"\"\"\n        Default for the get_or_create based on a dict.\n\n        The method uses only relevant identifiers based on ``DOR.id_fields``.\n\n        By default, all strings are set to lower case (option ``lower_strings``).\n        \"\"\"\n        definition = {key: x[key] for key in cls.DOR.id_fields}\n        for key, value in definition.items():\n            if value.__class__ == str and lower_strings:\n                definition[key] = value.lower()\n        return cls.objects.get_or_create(**definition)[0]\n\n    @classmethod\n    def get(cls, x):\n        \"\"\"\n        Default for the get_or_create based on a dict.\n\n        The method uses only relevant identifiers based on ``DOR.id_fields``.\n        \"\"\"\n        try:\n            definition = {key: x[key] for key in cls.DOR.id_fields}\n            result = cls.objects.get(**definition)\n        except cls.DoesNotExist:\n            result = None\n        return result\n\n    @classmethod\n    def default_form(cls):\n        \"\"\"\n        Creates a default form for all attributes defined in ``DOR.io_fields``.\n        \"\"\"\n\n        class DefaultForm(forms.ModelForm):\n            class Meta:\n                model = cls\n                fields = cls.DOR.io_fields\n\n        return DefaultForm\n\n    def to_dict(self):\n        \"\"\"\n        Uses the ``DOR.io_fields`` attribute to generate a default\n        dict object for the current instance.\n        \"\"\"\n        default_dict = {}\n        for field_name in self.DOR.io_fields:\n            field = eval(\"self.%s\" % field_name)\n            try:\n                default_dict[field_name] = field.pk\n            except AttributeError:\n                default_dict[field_name] = field\n        return default_dict\n\n    def title(self):\n        \"\"\"\n        Default for the title. It first looks for a valid label, next for a\n        valid name, and otherwise returns an empty string.\n        \"\"\"\n        try:\n            name = self.name\n        except AttributeError:\n            name = \"\"\n        try:\n            label = self.label\n        except AttributeError:\n            label = \"\"\n        return name if label == \"\" else label\n\n    def html_description(self):\n        \"\"\"\n        Uses the ddionrails Markdown parser (ddionrails.helpers) to render\n        the description into HTML.\n        \"\"\"\n        try:\n            html = render_markdown(self.description)\n        except AttributeError:\n            html = \"\"\n        return html\n\n    def get_attribute(self, attribute, default=None):\n        \"\"\"\n        Example::\n\n            study_id = variable.get_attribute(\"self.dataset.study.id\")\n        \"\"\"\n        try:\n            return eval(attribute)\n        except AttributeError:\n            return default\n\n    def string_id(self):\n        a = []\n        for field_name in self.DOR.id_fields:\n            field = eval(\"self.%s\" % field_name)\n            try:\n                s = field.string_id()\n            except AttributeError:\n                s = str(field)\n            a.append(s)\n        a = \"/\".join(a)\n        return a\n\n    def __str__(self):\n        return self.string_id()\n\n\nclass AdminMixin:\n    \"\"\" A mixin for ModelAdmins to query related models via methods \"\"\"\n\n    @staticmethod\n    def study_name(obj):\n        \"\"\" Return the name of the related study \"\"\"\n        try:\n            return obj.study.name\n        except AttributeError:\n            return None\n\n    @staticmethod\n    def period_name(obj):\n        \"\"\" Return the name of the related period \"\"\"\n        try:\n            return obj.period.name\n        except AttributeError:\n            return None\n\n    @staticmethod\n    def analysis_unit_name(obj):\n        \"\"\" Return the name of the related analysis_unit \"\"\"\n        try:\n            return obj.analysis_unit.name\n        except AttributeError:\n            return None\n\n    @staticmethod\n    def dataset_name(obj):\n        \"\"\" Return the name of the related dataset \"\"\"\n        try:\n            return obj.dataset.name\n        except AttributeError:\n            return None\n\n    @staticmethod\n    def dataset_study_name(obj):\n        \"\"\" Return the name of the related dataset.study \"\"\"\n        try:\n            return obj.dataset.study.name\n        except AttributeError:\n            return None\n\n    @staticmethod\n    def instrument_name(obj):\n        \"\"\" Return the name of the related instrument \"\"\"\n        try:\n            return obj.instrument.name\n        except AttributeError:\n            return None\n\n    @staticmethod\n    def instrument_study_name(obj):\n        \"\"\" Return the name of the related instrument.study \"\"\"\n        try:\n            return obj.instrument.study.name\n        except AttributeError:\n            return None\n\n    @staticmethod\n    def basket_name(obj):\n        \"\"\" Return the name of the related basket \"\"\"\n        try:\n            return obj.basket.name\n        except AttributeError:\n            return None\n\n    @staticmethod\n    def basket_study_name(obj):\n        \"\"\" Return the name of the related basket.study \"\"\"\n        try:\n            return obj.basket.study.name\n        except AttributeError:\n            return None\n\n    @staticmethod\n    def user_name(obj):\n        \"\"\" Return the name of the related basket.user \"\"\"\n        try:\n            return obj.basket.user.username\n        except AttributeError:\n            return None\n", "path": "ddionrails/base/mixins.py"}], "after_files": [{"content": "# -*- coding: utf-8 -*-\n\n\"\"\" Mixins for ddionrails.base app \"\"\"\n\nfrom typing import Dict\n\nfrom django import forms\n\nfrom config.helpers import render_markdown\n\n\nclass ModelMixin:\n    \"\"\"\n    Default mixins for all classes in DDI on Rails.\n\n    Requires two definition in the ``DOR`` class:\n\n    * io_fields: Fields that are used for the default form and in the default dict.\n    * id_fields: Fields that are used for the get_or_create default method.\n\n    Example:\n\n    ::\n\n        from django.db import models\n        from ddionrails.mixins import ModelMixin\n\n        class Test(models.Model, ModelMixin):\n\n            name = models.CharField(max_length=255, unique=True)\n\n            class DOR:\n                id_fields = [\"name\"]\n                io_fields = [\"name\"]\n\n    The default value for DOR is:\n\n    ::\n\n        class DOR:\n            id_fields = [\"name\"]\n            io_fields = [\"name\", \"label\", \"description\"]\n\n    The ``id_fields`` are also use to construct a default string identifier.\n    It is therefore recommended, to order them from the most general to the\n    most specific one.\n\n    \"\"\"\n\n    class DOR:\n        id_fields = [\"name\"]\n        io_fields = [\"name\", \"label\", \"description\"]\n\n    @classmethod\n    def get_or_create(cls, x, lower_strings=True):\n        \"\"\"\n        Default for the get_or_create based on a dict.\n\n        The method uses only relevant identifiers based on ``DOR.id_fields``.\n\n        By default, all strings are set to lower case (option ``lower_strings``).\n        \"\"\"\n        definition = {key: x[key] for key in cls.DOR.id_fields}\n        for key, value in definition.items():\n            if value.__class__ == str and lower_strings:\n                definition[key] = value.lower()\n        return cls.objects.get_or_create(**definition)[0]\n\n    @classmethod\n    def get(cls, parameters: Dict):\n        \"\"\"\n        Default for the get_or_create based on a dict.\n\n        The method uses only relevant identifiers based on ``DOR.id_fields``.\n        \"\"\"\n        try:\n            definition = {key: parameters[key] for key in cls.DOR.id_fields}\n            result = cls.objects.get(**definition)\n        except cls.DoesNotExist:\n            result = None\n        return result\n\n    @classmethod\n    def default_form(cls):\n        \"\"\"\n        Creates a default form for all attributes defined in ``DOR.io_fields``.\n        \"\"\"\n\n        class DefaultForm(forms.ModelForm):\n            class Meta:\n                model = cls\n                fields = cls.DOR.io_fields\n\n        return DefaultForm\n\n    def to_dict(self) -> Dict:\n        \"\"\"\n        Uses the ``DOR.io_fields`` attribute to generate a default\n        dict object for the current instance.\n        \"\"\"\n        dictionary = dict()\n        for field in self.DOR.io_fields:\n            value = getattr(self, field)\n            try:\n                dictionary[field] = value.pk\n            except AttributeError:\n                dictionary[field] = value\n        return dictionary\n\n    def title(self):\n        \"\"\"\n        Default for the title. It first looks for a valid label, next for a\n        valid name, and otherwise returns an empty string.\n        \"\"\"\n        try:\n            name = self.name\n        except AttributeError:\n            name = \"\"\n        try:\n            label = self.label\n        except AttributeError:\n            label = \"\"\n        return name if label == \"\" else label\n\n    def html_description(self):\n        \"\"\"\n        Uses the ddionrails Markdown parser (ddionrails.helpers) to render\n        the description into HTML.\n        \"\"\"\n        try:\n            html = render_markdown(self.description)\n        except AttributeError:\n            html = \"\"\n        return html\n\n    def __str__(self):\n        \"\"\" Returns a string reprensentation of the instance, using DOR.id_fields \"\"\"\n        result = []\n        for field in self.DOR.id_fields:\n            value = getattr(self, field)\n            try:\n                result.append(value.string_id())\n            except AttributeError:\n                result.append(str(value))\n        return \"/\".join(result)\n\n\nclass AdminMixin:\n    \"\"\" A mixin for ModelAdmins to query related models via methods \"\"\"\n\n    @staticmethod\n    def study_name(obj):\n        \"\"\" Return the name of the related study \"\"\"\n        try:\n            return obj.study.name\n        except AttributeError:\n            return None\n\n    @staticmethod\n    def period_name(obj):\n        \"\"\" Return the name of the related period \"\"\"\n        try:\n            return obj.period.name\n        except AttributeError:\n            return None\n\n    @staticmethod\n    def analysis_unit_name(obj):\n        \"\"\" Return the name of the related analysis_unit \"\"\"\n        try:\n            return obj.analysis_unit.name\n        except AttributeError:\n            return None\n\n    @staticmethod\n    def dataset_name(obj):\n        \"\"\" Return the name of the related dataset \"\"\"\n        try:\n            return obj.dataset.name\n        except AttributeError:\n            return None\n\n    @staticmethod\n    def dataset_study_name(obj):\n        \"\"\" Return the name of the related dataset.study \"\"\"\n        try:\n            return obj.dataset.study.name\n        except AttributeError:\n            return None\n\n    @staticmethod\n    def instrument_name(obj):\n        \"\"\" Return the name of the related instrument \"\"\"\n        try:\n            return obj.instrument.name\n        except AttributeError:\n            return None\n\n    @staticmethod\n    def instrument_study_name(obj):\n        \"\"\" Return the name of the related instrument.study \"\"\"\n        try:\n            return obj.instrument.study.name\n        except AttributeError:\n            return None\n\n    @staticmethod\n    def basket_name(obj):\n        \"\"\" Return the name of the related basket \"\"\"\n        try:\n            return obj.basket.name\n        except AttributeError:\n            return None\n\n    @staticmethod\n    def basket_study_name(obj):\n        \"\"\" Return the name of the related basket.study \"\"\"\n        try:\n            return obj.basket.study.name\n        except AttributeError:\n            return None\n\n    @staticmethod\n    def user_name(obj):\n        \"\"\" Return the name of the related basket.user \"\"\"\n        try:\n            return obj.basket.user.username\n        except AttributeError:\n            return None\n", "path": "ddionrails/base/mixins.py"}]}