• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

iplweb / bpp / 49150ee2-a89b-4df8-9538-55cb06c06872

24 Aug 2025 11:07PM UTC coverage: 42.715% (+1.5%) from 41.169%
49150ee2-a89b-4df8-9538-55cb06c06872

push

circleci

mpasternak
Merge branch 'release/v202508.1207'

1 of 1 new or added line in 1 file covered. (100.0%)

1119 existing lines in 82 files now uncovered.

16660 of 39003 relevant lines covered (42.71%)

1.16 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

83.54
src/bpp/models/util.py
1
"""Funkcje pomocnicze dla klas w bpp.models"""
2
from django.core.exceptions import ObjectDoesNotExist, ValidationError
3✔
3

4
from bpp.models.szablondlaopisubibliograficznego import SzablonDlaOpisuBibliograficznego
3✔
5

6
try:
3✔
7
    from django.core.urlresolvers import reverse
3✔
8
except ImportError:
3✔
9
    from django.urls import reverse
3✔
10

11
from django.db import models
3✔
12
from django.db.models import Max
3✔
13
from django.template.loader import get_template
3✔
14

15
from django.utils import safestring
3✔
16

17

18
def dodaj_autora(
3✔
19
    klass,
20
    rekord,
21
    autor,
22
    jednostka,
23
    zapisany_jako=None,
24
    typ_odpowiedzialnosci_skrot="aut.",
25
    kolejnosc=None,
26
    dyscyplina_naukowa=None,
27
    afiliuje=True,
28
):
29
    """
30
    Utility function, dodająca autora do danego rodzaju klasy (Wydawnictwo_Ciagle,
31
    Wydawnictwo_Zwarte, Patent); funkcja używana przez te klasy, niejako
32
    wewnętrzna dla całego API; nie powinna być używana bezpośrednio nigdzie,
33
    jedynie API tych klas winno być używane.
34

35
    :param klass:
36
    :param rekord:
37
    :param autor:
38
    :param jednostka:
39
    :param zapisany_jako:
40
    :param typ_odpowiedzialnosci_skrot:
41
    :param kolejnosc:
42
    :return:
43
    """
44

45
    from bpp.models import Typ_Odpowiedzialnosci
2✔
46

47
    typ_odpowiedzialnosci = Typ_Odpowiedzialnosci.objects.get(
2✔
48
        skrot=typ_odpowiedzialnosci_skrot
49
    )
50

51
    if zapisany_jako is None:
2✔
UNCOV
52
        zapisany_jako = f"{autor.nazwisko} {autor.imiona}"
1✔
53

54
    if kolejnosc is None:
2✔
55
        kolejnosc = klass.objects.filter(rekord=rekord).aggregate(Max("kolejnosc"))[
2✔
56
            "kolejnosc__max"
57
        ]
58
        if kolejnosc is None:
2✔
59
            kolejnosc = 0
2✔
60
        else:
61
            kolejnosc += 1
×
62

63
    inst = klass(
2✔
64
        rekord=rekord,
65
        autor=autor,
66
        jednostka=jednostka,
67
        typ_odpowiedzialnosci=typ_odpowiedzialnosci,
68
        kolejnosc=kolejnosc,
69
        zapisany_jako=zapisany_jako,
70
        dyscyplina_naukowa=dyscyplina_naukowa,
71
        afiliuje=afiliuje,
72
    )
73
    inst.full_clean()
2✔
74
    inst.save()
2✔
75
    return inst
2✔
76

77

78
class ModelZOpisemBibliograficznym(models.Model):
3✔
79
    """Mixin, umożliwiający renderowanie opisu bibliograficznego dla danego
80
    obiektu przy pomocy template."""
81

82
    tekst_przed_pierwszym_autorem = models.TextField(blank=True, null=True)
3✔
83
    tekst_po_ostatnim_autorze = models.TextField(blank=True, null=True)
3✔
84

85
    def opis_bibliograficzny(self, links=None):
3✔
86
        """Renderuje opis bibliograficzny dla danej klasy, używając:
87
        * w pierwszej kolejności zadeklarowanej Template dla danego typu rekordu (lub ogólnego Template),
88
        * w trzeciej kolejności templatki z dysku "opis_bibliograficzny/opis_bibliograficzny.html"
89

90
        :param links: "normal" lub "admin" jeżeli chcemy, aby autorzy prowadzili gdzieś (do stron browse/
91
        lub do admina).
92
        """
93

94
        template_name = SzablonDlaOpisuBibliograficznego.objects.get_for_model(self)
3✔
95
        if template_name is None:
3✔
96
            template_name = "opis_bibliograficzny.html"
3✔
97

98
        template = get_template(template_name)
3✔
99

100
        ret = (
3✔
101
            template.render(dict(praca=self, links=links))
102
            .replace("\r\n", "")
103
            .replace("\n", "")
104
        )
105
        while ret.find("  ") != -1:
3✔
106
            ret = ret.replace("  ", " ")
3✔
107

108
        return (
3✔
109
            ret.replace(" , ", ", ")
110
            .replace(" . ", ". ")
111
            .replace(". . ", ". ")
112
            .replace(". , ", ". ")
113
            .replace(" .", ".")
114
            .replace(".</b>[", ".</b> [")
115
        )
116

117
    def autorzy_dla_opisu(self):
3✔
118
        # Takie 'autorzy_set.all()' ale na potrzeby opisu bibliograficznego -- zaciąga
119
        # rekordy zależne za pomocą .select_related:
120

121
        if not self.pk:
3✔
122
            return []
3✔
123

124
        return self.autorzy_set.select_related(
3✔
125
            "autor", "typ_odpowiedzialnosci"
126
        ).order_by("kolejnosc")
127

128
    def get_slug(self):
3✔
129
        if self.pk is None:
3✔
130
            return
3✔
131

132
        from bpp.util import slugify_function
3✔
133

134
        slug_tytul_oryginalny = slugify_function(self.tytul_oryginalny)
3✔
135

136
        slug_trzech_pierwszych_autorow = []
3✔
137
        for wyd_autor in self.autorzy_set.all().select_related("autor")[:3]:
3✔
138
            slug_trzech_pierwszych_autorow.append(
×
139
                f"{wyd_autor.autor.nazwisko} {wyd_autor.autor.imiona[:1]}"
140
            )
141
        slug_trzech_pierwszych_autorow = " ".join(slug_trzech_pierwszych_autorow)
3✔
142

143
        if hasattr(self, "zrodlo_id") and self.zrodlo_id is not None:
3✔
144
            slug_zrodla = slugify_function(self.zrodlo.nazwa)
1✔
145
        elif (
2✔
146
            hasattr(self, "wydawnictwo_nadrzedne")
147
            and self.wydawnictwo_nadrzedne_id is not None
148
        ):
149
            slug_zrodla = slugify_function(self.wydawnictwo_nadrzedne.tytul_oryginalny)
×
150
        else:
151
            slug_zrodla = ""
2✔
152

153
        lt, la, lz = (
3✔
154
            len(slug_tytul_oryginalny),
155
            len(slug_trzech_pierwszych_autorow),
156
            len(slug_zrodla),
157
        )
158

159
        if lt + la + lz >= 350:
3✔
160
            if lt > 200:
×
161
                lt = 200
×
162

163
            if lt + la + lz >= 350:
×
164
                if lz > 100:
×
165
                    lz = 100
×
166

167
                if lt + la + lz >= 350:
×
168
                    la = 50
×
169

170
        from django.contrib.contenttypes.models import ContentType
3✔
171

172
        ret = "-".join(
3✔
173
            [
174
                slug_tytul_oryginalny[:lt],
175
                slug_zrodla[:lz],
176
                slug_trzech_pierwszych_autorow[:la],
177
                str(ContentType.objects.get_for_model(self).pk),
178
                str(self.pk),
179
            ]
180
        )
181

182
        return slugify_function(ret)
3✔
183

184
    # Ten obiekt stanowi bazę do późniejszego zapełniania pól w podklasach. Pola,
185
    # które powinna podklasa definiować to:
186
    #
187
    # opis_bibliograficzny_cache = models.TextField(default="")
188
    # - generowane przez self.opis_bibliograficzny()
189
    #
190
    # opis_bibliograficzny_autorzy_cache = ArrayField(TextField(), blank=True, null=True)
191
    # -  To pole używane jest na ten moment jedynie przez moduł OAI, do szybkiego
192
    #    produkowania pola "Creator" dla formatu Dublin Core, vide moduł bpp.oai .
193
    #    To pole zawiera listę autorów, w kolejności, nazwisko i imię, bez
194
    #    tytułu
195
    #
196
    # slug = models.SlugField(max_length=400, unique=True, db_index=True, null=True, blank=True)
197
    # - skrót dla rekordu, dla SEO, zależy od m.in. tytułu, autorów, wydawnictwa nadrzędnego, źródła
198
    #
199
    # opis_bibliograficzny_zapisani_autorzy_cache = models.TextField(default="")
200
    # - zależy od klas autorów; to pole używane jest przez Raport autorów oraz Raport
201
    #   jednostek do szybkiego wypluwania listy zapisanych nazwisk
202
    #
203
    # def zaktualizuj_opis_bibliograficzny_cache(self, tylko_opis=False):
204
    #     autorzy = self.autorzy_dla_opisu()
205
    #     self.opis_bibliograficzny_cache = self.opis_bibliograficzny()
206
    #     self.slug = self._get_slug()
207
    #
208
    #     if hasattr(self, "autor"):
209
    #         zapisani = ["%s %s" % (autorzy[0].autor.nazwisko, autorzy[0].autor.imiona)]
210
    #     else:
211
    #         zapisani = [x.zapisany_jako for x in autorzy]
212
    #
213
    #     oac = ["%s %s" % (x.autor.nazwisko, x.autor.imiona) for x in autorzy]
214
    #     self.opis_bibliograficzny_autorzy_cache = oac
215
    #
216
    #     ozac = ", ".join(zapisani)
217
    #     self.opis_bibliograficzny_zapisani_autorzy_cache = ozac
218

219
    class Meta:
3✔
220
        abstract = True
3✔
221

222

223
class ZapobiegajNiewlasciwymCharakterom(models.Model):
3✔
224
    class Meta:
3✔
225
        abstract = True
3✔
226

227
    def clean_fields(self, *args, **kw):
3✔
228
        try:
2✔
229
            cf = self.charakter_formalny
2✔
230
        except ObjectDoesNotExist:
×
231
            cf = None
×
232

233
        if cf is not None:
2✔
234
            if self.charakter_formalny.skrot in ["D", "H", "PAT"]:
2✔
235
                raise ValidationError(
×
236
                    {
237
                        "charakter_formalny": [
238
                            safestring.mark_safe(
239
                                'Jeżeli chcesz dodać rekord o typie "%s"'
240
                                ', <a href="%s">kliknij tutaj</a>.'
241
                                % (
242
                                    self.charakter_formalny.nazwa,
243
                                    reverse(
244
                                        "admin:bpp_%s_add"
245
                                        % self.charakter_formalny.nazwa.lower().replace(
246
                                            " ", "_"
247
                                        )
248
                                    ),
249
                                )
250
                            )
251
                        ]
252
                    }
253
                )
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc