We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Баг: При попытке добавления экспертизы в Профиль ошибка Server Error (500)
https://vas3k.club/profile/expertise/add/

Это если попытаться добавить Экспертизу с таким же именем каким уже была добавленна, хотел для теста попробовать такую же добавить, но с другим уровнем экспертизы. Получил ошибку Server Error (500).

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `common/data/expertise.py`
Content:
```
1 EXPERTISE = [
2     ("Хард-скиллы", [
3         ("frontend", "Фронтенд"),
4         ("backend", "Бекенд"),
5         ("mobile", "Мобильная разработка"),
6         ("machine-learning", "Машинное Обучение"),
7         ("data", "Данные и аналитика"),
8         ("infra", "Инфраструктура"),
9         ("crypto", "Крипта"),
10         ("qa", "QA"),
11         ("devops", "DevOps"),
12         ("hardware", "Хардварь"),
13         ("imaging", "Компьютерное зрение"),
14         ("nlp", "NLP"),
15         ("iot", "IoT"),
16         ("ux", "UX/UI"),
17         ("pm", "Продакт-менеджмент"),
18         ("security", "Безопасность"),
19         ("marketing", "Маркетинг"),
20         ("video", "Видео-продакшен"),
21         ("audio", "Аудио"),
22         ("copywriting", "Копирайтинг"),
23         ("design", "Дизайн"),
24         ("science", "Наука"),
25         ("business", "Бизнес"),
26     ]),
27     ("Софт-скиллы", [
28         ("hire", "Найм людей"),
29         ("lead", "Управление командами"),
30         ("critical", "Критическое мышление"),
31         ("rationality", "Рациональность"),
32         ("conflicts", "Решение конфликтов"),
33         ("coaching", "Менторинг"),
34         ("public-speaking", "Публичные выступления"),
35         ("planning", "Планирование"),
36         ("ethics", "Этика"),
37     ]),
38     ("Языки", [
39         ("python", "Python"),
40         ("java", "Java"),
41         ("javascript", "JavaScript"),
42         ("go", "Go"),
43         ("php", "PHP"),
44         ("ruby", "Ruby"),
45         ("swift", "Swift"),
46         ("cplus", "C/C++"),
47         ("csharp", "C#"),
48     ])
49 ]
50
```

Path: `users/forms/profile.py`
Content:
```
1 from django import forms
2 from django.core.exceptions import ValidationError
3 from django.forms import ModelForm
4 
5 from common.data.countries import COUNTRIES
6 from common.data.expertise import EXPERTISE
7 from users.models.user import User
8 from users.models.expertise import UserExpertise
9 from common.forms import ImageUploadField
10 
11 
12 class ProfileEditForm(ModelForm):
13     full_name = forms.CharField(
14         label="Имя и фамилия",
15         required=True,
16         max_length=128
17     )
18     avatar = ImageUploadField(
19         label="Аватар",
20         required=False,
21         resize=(512, 512),
22         convert_to="jpg",
23     )
24     city = forms.CharField(
25         label="город",
26         required=True,
27         max_length=120
28     )
29     country = forms.ChoiceField(
30         label="Страна",
31         choices=COUNTRIES,
32         required=True
33     )
34     bio = forms.CharField(
35         label="Ссылочки на себя и всякое такое",
36         required=False,
37         max_length=1024,
38         widget=forms.Textarea(attrs={"maxlength": 1024}),
39     )
40     company = forms.CharField(
41         label="Компания",
42         required=True,
43         max_length=128
44     )
45     position = forms.CharField(
46         label="Должность или что вы делаете",
47         required=True,
48         max_length=128
49     )
50     contact = forms.CharField(
51         label="Контакт для связи",
52         required=True,
53         max_length=256,
54     )
55 
56     class Meta:
57         model = User
58         fields = [
59             "full_name",
60             "avatar",
61             "company",
62             "position",
63             "city",
64             "country",
65             "bio",
66             "contact",
67         ]
68 
69 
70 class NotificationsEditForm(ModelForm):
71     email_digest_type = forms.ChoiceField(
72         label="Тип email-дайджеста",
73         required=True,
74         choices=User.EMAIL_DIGEST_TYPES,
75         initial=User.EMAIL_DIGEST_TYPE_WEEKLY,
76         widget=forms.RadioSelect(),
77     )
78 
79     class Meta:
80         model = User
81         fields = [
82             "email_digest_type",
83         ]
84 
85 
86 class ExpertiseForm(ModelForm):
87     expertise = forms.ChoiceField(
88         label="Область",
89         required=True,
90         choices=EXPERTISE + [("custom", "[добавить своё]")],
91     )
92     expertise_custom = forms.CharField(
93         label="Свой вариант",
94         required=False,
95         max_length=32
96     )
97     value = forms.IntegerField(
98         label="Скилл",
99         min_value=0,
100         max_value=100,
101         required=True,
102         widget=forms.NumberInput(attrs={"type": "range", "step": "1"}),
103     )
104 
105     class Meta:
106         model = UserExpertise
107         fields = ["expertise", "value"]
108 
109     def clean(self):
110         super().clean()
111         custom_expertise = self.cleaned_data.get("expertise_custom")
112         if custom_expertise:
113             self.cleaned_data["expertise"] = custom_expertise
114 
115         if not self.cleaned_data["expertise"]:
116             raise ValidationError("Name is required")
117
```

Path: `users/models/expertise.py`
Content:
```
1 from uuid import uuid4
2 
3 from django.db import models
4 from slugify import slugify
5 
6 from common.data.colors import COOL_COLORS
7 from common.data.expertise import EXPERTISE
8 from users.models.user import User
9 
10 
11 class UserExpertise(models.Model):
12     id = models.UUIDField(primary_key=True, default=uuid4, editable=False)
13     user = models.ForeignKey(User, related_name="expertise", on_delete=models.CASCADE)
14     expertise = models.CharField(max_length=32, null=False, db_index=True)
15     name = models.CharField(max_length=64, null=False)
16     value = models.IntegerField(default=0, null=False)
17     created_at = models.DateTimeField(auto_now_add=True)
18 
19     class Meta:
20         db_table = "user_expertise"
21         unique_together = [["expertise", "user"]]
22         ordering = ["created_at"]
23 
24     def save(self, *args, **kwargs):
25         pre_defined_expertise = dict(sum([e[1] for e in EXPERTISE], []))  # flatten nested items
26 
27         if not self.name:
28             self.name = pre_defined_expertise.get(self.expertise) or self.expertise
29 
30         if self.expertise not in pre_defined_expertise:
31             self.expertise = slugify(self.expertise.lower())[:32]
32 
33         return super().save(*args, **kwargs)
34 
35     @property
36     def color(self):
37         return COOL_COLORS[hash(self.name) % len(COOL_COLORS)]
38
```
--- 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/common/data/expertise.py b/common/data/expertise.py
--- a/common/data/expertise.py
+++ b/common/data/expertise.py
@@ -1,3 +1,5 @@
+from itertools import chain
+
 EXPERTISE = [
     ("Хард-скиллы", [
         ("frontend", "Фронтенд"),
@@ -47,3 +49,6 @@
         ("csharp", "C#"),
     ])
 ]
+
+
+EXPERTISE_FLAT_MAP = dict(chain.from_iterable(items for _, items in EXPERTISE))
diff --git a/users/forms/profile.py b/users/forms/profile.py
--- a/users/forms/profile.py
+++ b/users/forms/profile.py
@@ -110,7 +110,15 @@
         super().clean()
         custom_expertise = self.cleaned_data.get("expertise_custom")
         if custom_expertise:
-            self.cleaned_data["expertise"] = custom_expertise
+            self.cleaned_data["expertise"] = UserExpertise.make_custom_expertise_slug(custom_expertise)
 
         if not self.cleaned_data["expertise"]:
             raise ValidationError("Name is required")
+
+    def save(self, commit=True):
+        instance = super().save(commit=commit)
+        custom_expertise = self.cleaned_data.get("expertise_custom")
+        if custom_expertise:
+            instance.name = custom_expertise
+        return instance
+
diff --git a/users/models/expertise.py b/users/models/expertise.py
--- a/users/models/expertise.py
+++ b/users/models/expertise.py
@@ -4,14 +4,16 @@
 from slugify import slugify
 
 from common.data.colors import COOL_COLORS
-from common.data.expertise import EXPERTISE
+from common.data.expertise import EXPERTISE_FLAT_MAP
 from users.models.user import User
 
 
 class UserExpertise(models.Model):
+    EXPERTISE_SLUG_LENGTH = 32
+
     id = models.UUIDField(primary_key=True, default=uuid4, editable=False)
     user = models.ForeignKey(User, related_name="expertise", on_delete=models.CASCADE)
-    expertise = models.CharField(max_length=32, null=False, db_index=True)
+    expertise = models.CharField(max_length=EXPERTISE_SLUG_LENGTH, null=False, db_index=True)
     name = models.CharField(max_length=64, null=False)
     value = models.IntegerField(default=0, null=False)
     created_at = models.DateTimeField(auto_now_add=True)
@@ -22,16 +24,19 @@
         ordering = ["created_at"]
 
     def save(self, *args, **kwargs):
-        pre_defined_expertise = dict(sum([e[1] for e in EXPERTISE], []))  # flatten nested items
 
         if not self.name:
-            self.name = pre_defined_expertise.get(self.expertise) or self.expertise
+            self.name = EXPERTISE_FLAT_MAP.get(self.expertise) or self.expertise
 
-        if self.expertise not in pre_defined_expertise:
-            self.expertise = slugify(self.expertise.lower())[:32]
+        if self.expertise not in EXPERTISE_FLAT_MAP:
+            self.expertise = self.make_custom_expertise_slug(self.expertise)
 
         return super().save(*args, **kwargs)
 
     @property
     def color(self):
         return COOL_COLORS[hash(self.name) % len(COOL_COLORS)]
+
+    @classmethod
+    def make_custom_expertise_slug(cls, expertise_name: str):
+        return slugify(expertise_name.lower())[:cls.EXPERTISE_SLUG_LENGTH]

{"golden_diff": "diff --git a/common/data/expertise.py b/common/data/expertise.py\n--- a/common/data/expertise.py\n+++ b/common/data/expertise.py\n@@ -1,3 +1,5 @@\n+from itertools import chain\n+\n EXPERTISE = [\n     (\"\u0425\u0430\u0440\u0434-\u0441\u043a\u0438\u043b\u043b\u044b\", [\n         (\"frontend\", \"\u0424\u0440\u043e\u043d\u0442\u0435\u043d\u0434\"),\n@@ -47,3 +49,6 @@\n         (\"csharp\", \"C#\"),\n     ])\n ]\n+\n+\n+EXPERTISE_FLAT_MAP = dict(chain.from_iterable(items for _, items in EXPERTISE))\ndiff --git a/users/forms/profile.py b/users/forms/profile.py\n--- a/users/forms/profile.py\n+++ b/users/forms/profile.py\n@@ -110,7 +110,15 @@\n         super().clean()\n         custom_expertise = self.cleaned_data.get(\"expertise_custom\")\n         if custom_expertise:\n-            self.cleaned_data[\"expertise\"] = custom_expertise\n+            self.cleaned_data[\"expertise\"] = UserExpertise.make_custom_expertise_slug(custom_expertise)\n \n         if not self.cleaned_data[\"expertise\"]:\n             raise ValidationError(\"Name is required\")\n+\n+    def save(self, commit=True):\n+        instance = super().save(commit=commit)\n+        custom_expertise = self.cleaned_data.get(\"expertise_custom\")\n+        if custom_expertise:\n+            instance.name = custom_expertise\n+        return instance\n+\ndiff --git a/users/models/expertise.py b/users/models/expertise.py\n--- a/users/models/expertise.py\n+++ b/users/models/expertise.py\n@@ -4,14 +4,16 @@\n from slugify import slugify\n \n from common.data.colors import COOL_COLORS\n-from common.data.expertise import EXPERTISE\n+from common.data.expertise import EXPERTISE_FLAT_MAP\n from users.models.user import User\n \n \n class UserExpertise(models.Model):\n+    EXPERTISE_SLUG_LENGTH = 32\n+\n     id = models.UUIDField(primary_key=True, default=uuid4, editable=False)\n     user = models.ForeignKey(User, related_name=\"expertise\", on_delete=models.CASCADE)\n-    expertise = models.CharField(max_length=32, null=False, db_index=True)\n+    expertise = models.CharField(max_length=EXPERTISE_SLUG_LENGTH, null=False, db_index=True)\n     name = models.CharField(max_length=64, null=False)\n     value = models.IntegerField(default=0, null=False)\n     created_at = models.DateTimeField(auto_now_add=True)\n@@ -22,16 +24,19 @@\n         ordering = [\"created_at\"]\n \n     def save(self, *args, **kwargs):\n-        pre_defined_expertise = dict(sum([e[1] for e in EXPERTISE], []))  # flatten nested items\n \n         if not self.name:\n-            self.name = pre_defined_expertise.get(self.expertise) or self.expertise\n+            self.name = EXPERTISE_FLAT_MAP.get(self.expertise) or self.expertise\n \n-        if self.expertise not in pre_defined_expertise:\n-            self.expertise = slugify(self.expertise.lower())[:32]\n+        if self.expertise not in EXPERTISE_FLAT_MAP:\n+            self.expertise = self.make_custom_expertise_slug(self.expertise)\n \n         return super().save(*args, **kwargs)\n \n     @property\n     def color(self):\n         return COOL_COLORS[hash(self.name) % len(COOL_COLORS)]\n+\n+    @classmethod\n+    def make_custom_expertise_slug(cls, expertise_name: str):\n+        return slugify(expertise_name.lower())[:cls.EXPERTISE_SLUG_LENGTH]\n", "issue": "\u0411\u0430\u0433: \u041f\u0440\u0438 \u043f\u043e\u043f\u044b\u0442\u043a\u0435 \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u044d\u043a\u0441\u043f\u0435\u0440\u0442\u0438\u0437\u044b \u0432 \u041f\u0440\u043e\u0444\u0438\u043b\u044c \u043e\u0448\u0438\u0431\u043a\u0430 Server Error (500)\nhttps://vas3k.club/profile/expertise/add/\r\n\r\n\u042d\u0442\u043e \u0435\u0441\u043b\u0438 \u043f\u043e\u043f\u044b\u0442\u0430\u0442\u044c\u0441\u044f \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u042d\u043a\u0441\u043f\u0435\u0440\u0442\u0438\u0437\u0443 \u0441 \u0442\u0430\u043a\u0438\u043c \u0436\u0435 \u0438\u043c\u0435\u043d\u0435\u043c \u043a\u0430\u043a\u0438\u043c \u0443\u0436\u0435 \u0431\u044b\u043b\u0430 \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u043d\u0430, \u0445\u043e\u0442\u0435\u043b \u0434\u043b\u044f \u0442\u0435\u0441\u0442\u0430 \u043f\u043e\u043f\u0440\u043e\u0431\u043e\u0432\u0430\u0442\u044c \u0442\u0430\u043a\u0443\u044e \u0436\u0435 \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c, \u043d\u043e \u0441 \u0434\u0440\u0443\u0433\u0438\u043c \u0443\u0440\u043e\u0432\u043d\u0435\u043c \u044d\u043a\u0441\u043f\u0435\u0440\u0442\u0438\u0437\u044b. \u041f\u043e\u043b\u0443\u0447\u0438\u043b \u043e\u0448\u0438\u0431\u043a\u0443 Server Error (500).\n", "before_files": [{"content": "EXPERTISE = [\n    (\"\u0425\u0430\u0440\u0434-\u0441\u043a\u0438\u043b\u043b\u044b\", [\n        (\"frontend\", \"\u0424\u0440\u043e\u043d\u0442\u0435\u043d\u0434\"),\n        (\"backend\", \"\u0411\u0435\u043a\u0435\u043d\u0434\"),\n        (\"mobile\", \"\u041c\u043e\u0431\u0438\u043b\u044c\u043d\u0430\u044f \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0430\"),\n        (\"machine-learning\", \"\u041c\u0430\u0448\u0438\u043d\u043d\u043e\u0435 \u041e\u0431\u0443\u0447\u0435\u043d\u0438\u0435\"),\n        (\"data\", \"\u0414\u0430\u043d\u043d\u044b\u0435 \u0438 \u0430\u043d\u0430\u043b\u0438\u0442\u0438\u043a\u0430\"),\n        (\"infra\", \"\u0418\u043d\u0444\u0440\u0430\u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0430\"),\n        (\"crypto\", \"\u041a\u0440\u0438\u043f\u0442\u0430\"),\n        (\"qa\", \"QA\"),\n        (\"devops\", \"DevOps\"),\n        (\"hardware\", \"\u0425\u0430\u0440\u0434\u0432\u0430\u0440\u044c\"),\n        (\"imaging\", \"\u041a\u043e\u043c\u043f\u044c\u044e\u0442\u0435\u0440\u043d\u043e\u0435 \u0437\u0440\u0435\u043d\u0438\u0435\"),\n        (\"nlp\", \"NLP\"),\n        (\"iot\", \"IoT\"),\n        (\"ux\", \"UX/UI\"),\n        (\"pm\", \"\u041f\u0440\u043e\u0434\u0430\u043a\u0442-\u043c\u0435\u043d\u0435\u0434\u0436\u043c\u0435\u043d\u0442\"),\n        (\"security\", \"\u0411\u0435\u0437\u043e\u043f\u0430\u0441\u043d\u043e\u0441\u0442\u044c\"),\n        (\"marketing\", \"\u041c\u0430\u0440\u043a\u0435\u0442\u0438\u043d\u0433\"),\n        (\"video\", \"\u0412\u0438\u0434\u0435\u043e-\u043f\u0440\u043e\u0434\u0430\u043a\u0448\u0435\u043d\"),\n        (\"audio\", \"\u0410\u0443\u0434\u0438\u043e\"),\n        (\"copywriting\", \"\u041a\u043e\u043f\u0438\u0440\u0430\u0439\u0442\u0438\u043d\u0433\"),\n        (\"design\", \"\u0414\u0438\u0437\u0430\u0439\u043d\"),\n        (\"science\", \"\u041d\u0430\u0443\u043a\u0430\"),\n        (\"business\", \"\u0411\u0438\u0437\u043d\u0435\u0441\"),\n    ]),\n    (\"\u0421\u043e\u0444\u0442-\u0441\u043a\u0438\u043b\u043b\u044b\", [\n        (\"hire\", \"\u041d\u0430\u0439\u043c \u043b\u044e\u0434\u0435\u0439\"),\n        (\"lead\", \"\u0423\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u043a\u043e\u043c\u0430\u043d\u0434\u0430\u043c\u0438\"),\n        (\"critical\", \"\u041a\u0440\u0438\u0442\u0438\u0447\u0435\u0441\u043a\u043e\u0435 \u043c\u044b\u0448\u043b\u0435\u043d\u0438\u0435\"),\n        (\"rationality\", \"\u0420\u0430\u0446\u0438\u043e\u043d\u0430\u043b\u044c\u043d\u043e\u0441\u0442\u044c\"),\n        (\"conflicts\", \"\u0420\u0435\u0448\u0435\u043d\u0438\u0435 \u043a\u043e\u043d\u0444\u043b\u0438\u043a\u0442\u043e\u0432\"),\n        (\"coaching\", \"\u041c\u0435\u043d\u0442\u043e\u0440\u0438\u043d\u0433\"),\n        (\"public-speaking\", \"\u041f\u0443\u0431\u043b\u0438\u0447\u043d\u044b\u0435 \u0432\u044b\u0441\u0442\u0443\u043f\u043b\u0435\u043d\u0438\u044f\"),\n        (\"planning\", \"\u041f\u043b\u0430\u043d\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435\"),\n        (\"ethics\", \"\u042d\u0442\u0438\u043a\u0430\"),\n    ]),\n    (\"\u042f\u0437\u044b\u043a\u0438\", [\n        (\"python\", \"Python\"),\n        (\"java\", \"Java\"),\n        (\"javascript\", \"JavaScript\"),\n        (\"go\", \"Go\"),\n        (\"php\", \"PHP\"),\n        (\"ruby\", \"Ruby\"),\n        (\"swift\", \"Swift\"),\n        (\"cplus\", \"C/C++\"),\n        (\"csharp\", \"C#\"),\n    ])\n]\n", "path": "common/data/expertise.py"}, {"content": "from django import forms\nfrom django.core.exceptions import ValidationError\nfrom django.forms import ModelForm\n\nfrom common.data.countries import COUNTRIES\nfrom common.data.expertise import EXPERTISE\nfrom users.models.user import User\nfrom users.models.expertise import UserExpertise\nfrom common.forms import ImageUploadField\n\n\nclass ProfileEditForm(ModelForm):\n    full_name = forms.CharField(\n        label=\"\u0418\u043c\u044f \u0438 \u0444\u0430\u043c\u0438\u043b\u0438\u044f\",\n        required=True,\n        max_length=128\n    )\n    avatar = ImageUploadField(\n        label=\"\u0410\u0432\u0430\u0442\u0430\u0440\",\n        required=False,\n        resize=(512, 512),\n        convert_to=\"jpg\",\n    )\n    city = forms.CharField(\n        label=\"\u0433\u043e\u0440\u043e\u0434\",\n        required=True,\n        max_length=120\n    )\n    country = forms.ChoiceField(\n        label=\"\u0421\u0442\u0440\u0430\u043d\u0430\",\n        choices=COUNTRIES,\n        required=True\n    )\n    bio = forms.CharField(\n        label=\"\u0421\u0441\u044b\u043b\u043e\u0447\u043a\u0438 \u043d\u0430 \u0441\u0435\u0431\u044f \u0438 \u0432\u0441\u044f\u043a\u043e\u0435 \u0442\u0430\u043a\u043e\u0435\",\n        required=False,\n        max_length=1024,\n        widget=forms.Textarea(attrs={\"maxlength\": 1024}),\n    )\n    company = forms.CharField(\n        label=\"\u041a\u043e\u043c\u043f\u0430\u043d\u0438\u044f\",\n        required=True,\n        max_length=128\n    )\n    position = forms.CharField(\n        label=\"\u0414\u043e\u043b\u0436\u043d\u043e\u0441\u0442\u044c \u0438\u043b\u0438 \u0447\u0442\u043e \u0432\u044b \u0434\u0435\u043b\u0430\u0435\u0442\u0435\",\n        required=True,\n        max_length=128\n    )\n    contact = forms.CharField(\n        label=\"\u041a\u043e\u043d\u0442\u0430\u043a\u0442 \u0434\u043b\u044f \u0441\u0432\u044f\u0437\u0438\",\n        required=True,\n        max_length=256,\n    )\n\n    class Meta:\n        model = User\n        fields = [\n            \"full_name\",\n            \"avatar\",\n            \"company\",\n            \"position\",\n            \"city\",\n            \"country\",\n            \"bio\",\n            \"contact\",\n        ]\n\n\nclass NotificationsEditForm(ModelForm):\n    email_digest_type = forms.ChoiceField(\n        label=\"\u0422\u0438\u043f email-\u0434\u0430\u0439\u0434\u0436\u0435\u0441\u0442\u0430\",\n        required=True,\n        choices=User.EMAIL_DIGEST_TYPES,\n        initial=User.EMAIL_DIGEST_TYPE_WEEKLY,\n        widget=forms.RadioSelect(),\n    )\n\n    class Meta:\n        model = User\n        fields = [\n            \"email_digest_type\",\n        ]\n\n\nclass ExpertiseForm(ModelForm):\n    expertise = forms.ChoiceField(\n        label=\"\u041e\u0431\u043b\u0430\u0441\u0442\u044c\",\n        required=True,\n        choices=EXPERTISE + [(\"custom\", \"[\u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0441\u0432\u043e\u0451]\")],\n    )\n    expertise_custom = forms.CharField(\n        label=\"\u0421\u0432\u043e\u0439 \u0432\u0430\u0440\u0438\u0430\u043d\u0442\",\n        required=False,\n        max_length=32\n    )\n    value = forms.IntegerField(\n        label=\"\u0421\u043a\u0438\u043b\u043b\",\n        min_value=0,\n        max_value=100,\n        required=True,\n        widget=forms.NumberInput(attrs={\"type\": \"range\", \"step\": \"1\"}),\n    )\n\n    class Meta:\n        model = UserExpertise\n        fields = [\"expertise\", \"value\"]\n\n    def clean(self):\n        super().clean()\n        custom_expertise = self.cleaned_data.get(\"expertise_custom\")\n        if custom_expertise:\n            self.cleaned_data[\"expertise\"] = custom_expertise\n\n        if not self.cleaned_data[\"expertise\"]:\n            raise ValidationError(\"Name is required\")\n", "path": "users/forms/profile.py"}, {"content": "from uuid import uuid4\n\nfrom django.db import models\nfrom slugify import slugify\n\nfrom common.data.colors import COOL_COLORS\nfrom common.data.expertise import EXPERTISE\nfrom users.models.user import User\n\n\nclass UserExpertise(models.Model):\n    id = models.UUIDField(primary_key=True, default=uuid4, editable=False)\n    user = models.ForeignKey(User, related_name=\"expertise\", on_delete=models.CASCADE)\n    expertise = models.CharField(max_length=32, null=False, db_index=True)\n    name = models.CharField(max_length=64, null=False)\n    value = models.IntegerField(default=0, null=False)\n    created_at = models.DateTimeField(auto_now_add=True)\n\n    class Meta:\n        db_table = \"user_expertise\"\n        unique_together = [[\"expertise\", \"user\"]]\n        ordering = [\"created_at\"]\n\n    def save(self, *args, **kwargs):\n        pre_defined_expertise = dict(sum([e[1] for e in EXPERTISE], []))  # flatten nested items\n\n        if not self.name:\n            self.name = pre_defined_expertise.get(self.expertise) or self.expertise\n\n        if self.expertise not in pre_defined_expertise:\n            self.expertise = slugify(self.expertise.lower())[:32]\n\n        return super().save(*args, **kwargs)\n\n    @property\n    def color(self):\n        return COOL_COLORS[hash(self.name) % len(COOL_COLORS)]\n", "path": "users/models/expertise.py"}], "after_files": [{"content": "from itertools import chain\n\nEXPERTISE = [\n    (\"\u0425\u0430\u0440\u0434-\u0441\u043a\u0438\u043b\u043b\u044b\", [\n        (\"frontend\", \"\u0424\u0440\u043e\u043d\u0442\u0435\u043d\u0434\"),\n        (\"backend\", \"\u0411\u0435\u043a\u0435\u043d\u0434\"),\n        (\"mobile\", \"\u041c\u043e\u0431\u0438\u043b\u044c\u043d\u0430\u044f \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0430\"),\n        (\"machine-learning\", \"\u041c\u0430\u0448\u0438\u043d\u043d\u043e\u0435 \u041e\u0431\u0443\u0447\u0435\u043d\u0438\u0435\"),\n        (\"data\", \"\u0414\u0430\u043d\u043d\u044b\u0435 \u0438 \u0430\u043d\u0430\u043b\u0438\u0442\u0438\u043a\u0430\"),\n        (\"infra\", \"\u0418\u043d\u0444\u0440\u0430\u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0430\"),\n        (\"crypto\", \"\u041a\u0440\u0438\u043f\u0442\u0430\"),\n        (\"qa\", \"QA\"),\n        (\"devops\", \"DevOps\"),\n        (\"hardware\", \"\u0425\u0430\u0440\u0434\u0432\u0430\u0440\u044c\"),\n        (\"imaging\", \"\u041a\u043e\u043c\u043f\u044c\u044e\u0442\u0435\u0440\u043d\u043e\u0435 \u0437\u0440\u0435\u043d\u0438\u0435\"),\n        (\"nlp\", \"NLP\"),\n        (\"iot\", \"IoT\"),\n        (\"ux\", \"UX/UI\"),\n        (\"pm\", \"\u041f\u0440\u043e\u0434\u0430\u043a\u0442-\u043c\u0435\u043d\u0435\u0434\u0436\u043c\u0435\u043d\u0442\"),\n        (\"security\", \"\u0411\u0435\u0437\u043e\u043f\u0430\u0441\u043d\u043e\u0441\u0442\u044c\"),\n        (\"marketing\", \"\u041c\u0430\u0440\u043a\u0435\u0442\u0438\u043d\u0433\"),\n        (\"video\", \"\u0412\u0438\u0434\u0435\u043e-\u043f\u0440\u043e\u0434\u0430\u043a\u0448\u0435\u043d\"),\n        (\"audio\", \"\u0410\u0443\u0434\u0438\u043e\"),\n        (\"copywriting\", \"\u041a\u043e\u043f\u0438\u0440\u0430\u0439\u0442\u0438\u043d\u0433\"),\n        (\"design\", \"\u0414\u0438\u0437\u0430\u0439\u043d\"),\n        (\"science\", \"\u041d\u0430\u0443\u043a\u0430\"),\n        (\"business\", \"\u0411\u0438\u0437\u043d\u0435\u0441\"),\n    ]),\n    (\"\u0421\u043e\u0444\u0442-\u0441\u043a\u0438\u043b\u043b\u044b\", [\n        (\"hire\", \"\u041d\u0430\u0439\u043c \u043b\u044e\u0434\u0435\u0439\"),\n        (\"lead\", \"\u0423\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u043a\u043e\u043c\u0430\u043d\u0434\u0430\u043c\u0438\"),\n        (\"critical\", \"\u041a\u0440\u0438\u0442\u0438\u0447\u0435\u0441\u043a\u043e\u0435 \u043c\u044b\u0448\u043b\u0435\u043d\u0438\u0435\"),\n        (\"rationality\", \"\u0420\u0430\u0446\u0438\u043e\u043d\u0430\u043b\u044c\u043d\u043e\u0441\u0442\u044c\"),\n        (\"conflicts\", \"\u0420\u0435\u0448\u0435\u043d\u0438\u0435 \u043a\u043e\u043d\u0444\u043b\u0438\u043a\u0442\u043e\u0432\"),\n        (\"coaching\", \"\u041c\u0435\u043d\u0442\u043e\u0440\u0438\u043d\u0433\"),\n        (\"public-speaking\", \"\u041f\u0443\u0431\u043b\u0438\u0447\u043d\u044b\u0435 \u0432\u044b\u0441\u0442\u0443\u043f\u043b\u0435\u043d\u0438\u044f\"),\n        (\"planning\", \"\u041f\u043b\u0430\u043d\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435\"),\n        (\"ethics\", \"\u042d\u0442\u0438\u043a\u0430\"),\n    ]),\n    (\"\u042f\u0437\u044b\u043a\u0438\", [\n        (\"python\", \"Python\"),\n        (\"java\", \"Java\"),\n        (\"javascript\", \"JavaScript\"),\n        (\"go\", \"Go\"),\n        (\"php\", \"PHP\"),\n        (\"ruby\", \"Ruby\"),\n        (\"swift\", \"Swift\"),\n        (\"cplus\", \"C/C++\"),\n        (\"csharp\", \"C#\"),\n    ])\n]\n\n\nEXPERTISE_FLAT_MAP = dict(chain.from_iterable(items for _, items in EXPERTISE))\n", "path": "common/data/expertise.py"}, {"content": "from django import forms\nfrom django.core.exceptions import ValidationError\nfrom django.forms import ModelForm\n\nfrom common.data.countries import COUNTRIES\nfrom common.data.expertise import EXPERTISE\nfrom users.models.user import User\nfrom users.models.expertise import UserExpertise\nfrom common.forms import ImageUploadField\n\n\nclass ProfileEditForm(ModelForm):\n    full_name = forms.CharField(\n        label=\"\u0418\u043c\u044f \u0438 \u0444\u0430\u043c\u0438\u043b\u0438\u044f\",\n        required=True,\n        max_length=128\n    )\n    avatar = ImageUploadField(\n        label=\"\u0410\u0432\u0430\u0442\u0430\u0440\",\n        required=False,\n        resize=(512, 512),\n        convert_to=\"jpg\",\n    )\n    city = forms.CharField(\n        label=\"\u0433\u043e\u0440\u043e\u0434\",\n        required=True,\n        max_length=120\n    )\n    country = forms.ChoiceField(\n        label=\"\u0421\u0442\u0440\u0430\u043d\u0430\",\n        choices=COUNTRIES,\n        required=True\n    )\n    bio = forms.CharField(\n        label=\"\u0421\u0441\u044b\u043b\u043e\u0447\u043a\u0438 \u043d\u0430 \u0441\u0435\u0431\u044f \u0438 \u0432\u0441\u044f\u043a\u043e\u0435 \u0442\u0430\u043a\u043e\u0435\",\n        required=False,\n        max_length=1024,\n        widget=forms.Textarea(attrs={\"maxlength\": 1024}),\n    )\n    company = forms.CharField(\n        label=\"\u041a\u043e\u043c\u043f\u0430\u043d\u0438\u044f\",\n        required=True,\n        max_length=128\n    )\n    position = forms.CharField(\n        label=\"\u0414\u043e\u043b\u0436\u043d\u043e\u0441\u0442\u044c \u0438\u043b\u0438 \u0447\u0442\u043e \u0432\u044b \u0434\u0435\u043b\u0430\u0435\u0442\u0435\",\n        required=True,\n        max_length=128\n    )\n    contact = forms.CharField(\n        label=\"\u041a\u043e\u043d\u0442\u0430\u043a\u0442 \u0434\u043b\u044f \u0441\u0432\u044f\u0437\u0438\",\n        required=True,\n        max_length=256,\n    )\n\n    class Meta:\n        model = User\n        fields = [\n            \"full_name\",\n            \"avatar\",\n            \"company\",\n            \"position\",\n            \"city\",\n            \"country\",\n            \"bio\",\n            \"contact\",\n        ]\n\n\nclass NotificationsEditForm(ModelForm):\n    email_digest_type = forms.ChoiceField(\n        label=\"\u0422\u0438\u043f email-\u0434\u0430\u0439\u0434\u0436\u0435\u0441\u0442\u0430\",\n        required=True,\n        choices=User.EMAIL_DIGEST_TYPES,\n        initial=User.EMAIL_DIGEST_TYPE_WEEKLY,\n        widget=forms.RadioSelect(),\n    )\n\n    class Meta:\n        model = User\n        fields = [\n            \"email_digest_type\",\n        ]\n\n\nclass ExpertiseForm(ModelForm):\n    expertise = forms.ChoiceField(\n        label=\"\u041e\u0431\u043b\u0430\u0441\u0442\u044c\",\n        required=True,\n        choices=EXPERTISE + [(\"custom\", \"[\u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0441\u0432\u043e\u0451]\")],\n    )\n    expertise_custom = forms.CharField(\n        label=\"\u0421\u0432\u043e\u0439 \u0432\u0430\u0440\u0438\u0430\u043d\u0442\",\n        required=False,\n        max_length=32\n    )\n    value = forms.IntegerField(\n        label=\"\u0421\u043a\u0438\u043b\u043b\",\n        min_value=0,\n        max_value=100,\n        required=True,\n        widget=forms.NumberInput(attrs={\"type\": \"range\", \"step\": \"1\"}),\n    )\n\n    class Meta:\n        model = UserExpertise\n        fields = [\"expertise\", \"value\"]\n\n    def clean(self):\n        super().clean()\n        custom_expertise = self.cleaned_data.get(\"expertise_custom\")\n        if custom_expertise:\n            self.cleaned_data[\"expertise\"] = UserExpertise.make_custom_expertise_slug(custom_expertise)\n\n        if not self.cleaned_data[\"expertise\"]:\n            raise ValidationError(\"Name is required\")\n\n    def save(self, commit=True):\n        instance = super().save(commit=commit)\n        custom_expertise = self.cleaned_data.get(\"expertise_custom\")\n        if custom_expertise:\n            instance.name = custom_expertise\n        return instance\n\n", "path": "users/forms/profile.py"}, {"content": "from uuid import uuid4\n\nfrom django.db import models\nfrom slugify import slugify\n\nfrom common.data.colors import COOL_COLORS\nfrom common.data.expertise import EXPERTISE_FLAT_MAP\nfrom users.models.user import User\n\n\nclass UserExpertise(models.Model):\n    EXPERTISE_SLUG_LENGTH = 32\n\n    id = models.UUIDField(primary_key=True, default=uuid4, editable=False)\n    user = models.ForeignKey(User, related_name=\"expertise\", on_delete=models.CASCADE)\n    expertise = models.CharField(max_length=EXPERTISE_SLUG_LENGTH, null=False, db_index=True)\n    name = models.CharField(max_length=64, null=False)\n    value = models.IntegerField(default=0, null=False)\n    created_at = models.DateTimeField(auto_now_add=True)\n\n    class Meta:\n        db_table = \"user_expertise\"\n        unique_together = [[\"expertise\", \"user\"]]\n        ordering = [\"created_at\"]\n\n    def save(self, *args, **kwargs):\n\n        if not self.name:\n            self.name = EXPERTISE_FLAT_MAP.get(self.expertise) or self.expertise\n\n        if self.expertise not in EXPERTISE_FLAT_MAP:\n            self.expertise = self.make_custom_expertise_slug(self.expertise)\n\n        return super().save(*args, **kwargs)\n\n    @property\n    def color(self):\n        return COOL_COLORS[hash(self.name) % len(COOL_COLORS)]\n\n    @classmethod\n    def make_custom_expertise_slug(cls, expertise_name: str):\n        return slugify(expertise_name.lower())[:cls.EXPERTISE_SLUG_LENGTH]\n", "path": "users/models/expertise.py"}]}