Skip to content

Commit e70f54f

Browse files
stephenfinfstachura
authored andcommitted
models: Add submission labels
Labels are arbitrary bits of metadata attached to a submission. They can be used to signify priority, category, or other similar information. They can also be used to filter patches and identify the ones most interesting to a given user. Labels can be associated with a project to ensure that one project can use a totally different set of labels to another and to, in the future, allow a project administrator to use their own labels. However, they can also be global, which is useful for things that would be common across multiple projects such as "RFC".
1 parent bacb840 commit e70f54f

4 files changed

Lines changed: 159 additions & 1 deletion

File tree

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<django-objects version="1.0">
3+
<object model="patchwork.label" pk="1">
4+
<field name="project" rel="ManyToOneRel" to="patchwork.project"><None></None></field>
5+
<field name="name" type="CharField">RFC</field>
6+
<field name="description" type="TextField">"RFC" stands for "Request for Comment", which tells maintainers that they should review your patch thoroughly and provide feedback. RFC is typically used when sending feature patches for the first time, or anytime the patch is more than just a simple bug fix.</field>
7+
<field name="color" type="PositiveIntegerField">#EDEDED</field>
8+
</object>
9+
</django-objects>
Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
# Generated by Django 6.0.7 on 2026-07-31 21:26
2+
3+
import django.db.models.deletion
4+
import patchwork.fields
5+
from django.db import migrations, models
6+
7+
8+
class Migration(migrations.Migration):
9+
dependencies = [
10+
('patchwork', '0053_series_ordering_indexes'),
11+
]
12+
13+
operations = [
14+
migrations.CreateModel(
15+
name='Label',
16+
fields=[
17+
(
18+
'id',
19+
models.AutoField(
20+
auto_created=True,
21+
primary_key=True,
22+
serialize=False,
23+
verbose_name='ID',
24+
),
25+
),
26+
(
27+
'name',
28+
models.CharField(
29+
help_text='The label value.', max_length=25
30+
),
31+
),
32+
(
33+
'description',
34+
models.TextField(
35+
blank=True,
36+
help_text='A description of what the label is '
37+
'and when it should be applied.',
38+
null=True,
39+
),
40+
),
41+
(
42+
'color',
43+
patchwork.fields.ColorField(
44+
help_text='The color code to use in the UI.'
45+
),
46+
),
47+
(
48+
'project',
49+
models.ForeignKey(
50+
blank=True,
51+
help_text='The project this label is associated with. '
52+
'If unset, this label is global to the instance',
53+
null=True,
54+
on_delete=django.db.models.deletion.CASCADE,
55+
related_name='labels',
56+
related_query_name='label',
57+
to='patchwork.project',
58+
),
59+
),
60+
],
61+
options={
62+
'ordering': ['name'],
63+
'constraints': [
64+
models.UniqueConstraint(
65+
models.F('project'),
66+
django.db.models.functions.text.Lower('name'),
67+
name='uniq_labels_project_id_name',
68+
),
69+
],
70+
},
71+
),
72+
migrations.AddField(
73+
model_name='cover',
74+
name='labels',
75+
field=models.ManyToManyField(to='patchwork.label'),
76+
),
77+
migrations.AddField(
78+
model_name='patch',
79+
name='labels',
80+
field=models.ManyToManyField(to='patchwork.label'),
81+
),
82+
]

‎patchwork/models.py‎

Lines changed: 57 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,11 +15,12 @@
1515
from django.core.validators import validate_unicode_slug
1616
from django.core.validators import MaxValueValidator
1717
from django.db import models
18+
from django.db.models.constraints import UniqueConstraint
1819
from django.urls import reverse
1920
from django.utils.functional import cached_property
2021
from django.utils import timezone as tz_utils
2122

22-
from patchwork.fields import HashField
23+
from patchwork.fields import HashField, ColorField
2324
from patchwork.hasher import hash_diff
2425

2526
if settings.ENABLE_REST_API:
@@ -261,6 +262,60 @@ class Meta:
261262
ordering = ['ordering']
262263

263264

265+
class Label(models.Model):
266+
"""Labels for patches.
267+
268+
Labels are arbitrary bits of metadata attached to a patch. They can
269+
be used to signify priority, category, or other similar information.
270+
They can also be used to filter patches and identify the ones most
271+
interesting to a given user.
272+
"""
273+
274+
project = models.ForeignKey(
275+
Project,
276+
related_name='labels',
277+
related_query_name='label',
278+
null=True,
279+
blank=True,
280+
on_delete=models.CASCADE,
281+
help_text='The project this label is associated with. If unset, this '
282+
'label is global to the instance',
283+
)
284+
285+
name = models.CharField(max_length=25, help_text='The label value.')
286+
description = models.TextField(
287+
null=True,
288+
blank=True,
289+
help_text='A description of what the label is and when it should be '
290+
'applied.',
291+
)
292+
color = ColorField(help_text='The color code to use in the UI.')
293+
294+
def __str__(self):
295+
return self.name
296+
297+
@staticmethod
298+
def get_project_labels(project):
299+
result = {}
300+
project_labels = Label.objects.filter(
301+
models.Q(project=project) | models.Q(project__isnull=True)
302+
).all()
303+
304+
for label in project_labels:
305+
if label.name not in result or label.project is not None:
306+
result[label.name] = label
307+
308+
return list(result.values())
309+
310+
class Meta:
311+
ordering = ['name']
312+
constraints = [
313+
UniqueConstraint(
314+
'project', Lower('name'), name='uniq_labels_project_id_name'
315+
)
316+
]
317+
318+
264319
class Tag(models.Model):
265320
name = models.CharField(max_length=20)
266321
pattern = models.CharField(
@@ -441,6 +496,7 @@ class SubmissionMixin(FilenameMixin, EmailMixin, models.Model):
441496
# submission metadata
442497

443498
name = models.CharField(max_length=255)
499+
labels = models.ManyToManyField(Label)
444500

445501
@cached_property
446502
def list_archive_url(self):
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
---
2+
features:
3+
- |
4+
Add support for patch labels. Labels are a way to organize and prioritize
5+
submissions. You can apply labels to patches and cover letters to signify
6+
priority, category, or any other marker you wish.
7+
8+
Labels can be either global or tied to the project they are created in.
9+
Labels can have an optional description attached, which will provide a
10+
little insight into the purpose of the label. Labels are completely
11+
customizable and the labels available will vary by instance.

0 commit comments

Comments
 (0)