diff --git a/legacy.py b/legacy.py index 2b7c5cabf2e987f6e15c8c9c99811879caa7f812..868458262da8a2b1dbf5fbb949a5e50db4dd6a82 100644 --- a/legacy.py +++ b/legacy.py @@ -61,7 +61,7 @@ def import_old_protocols(sql_text): protocoltype = ProtocolType.query.filter(ProtocolType.short_name.ilike(handle)).first() if protocoltype is None: raise KeyError("No protocoltype for handle '{}'.".format(handle)) - protocol = Protocol(protocoltype.id, date, source=source) + protocol = Protocol(protocoltype_id=protocoltype.id, date=date, source=source) db.session.add(protocol) db.session.commit() import tasks diff --git a/models/database.py b/models/database.py index 776105d3ab11234591feb38354e3ab598533cf8e..d1a2aa061de3824799cb98cff85b8c568d7be0c4 100644 --- a/models/database.py +++ b/models/database.py @@ -33,6 +33,16 @@ class DatabaseModel(db.Model): def has_admin_right(self, user): return self.get_parent().has_admin_right(user) + def __repr__(self): + columns = [] + for column in self.__table__.columns: + column_name = column.key + value = getattr(self, column_name) + if isinstance(value, str): + value = "'" + value + "'" + columns.append("{}={}".format(column_name, value)) + return "{}({})".format(self.__class__.__name__, ", ".join(columns)) + class ProtocolType(DatabaseModel): __tablename__ = "protocoltypes" __model_name__ = "protocoltype" @@ -61,43 +71,6 @@ class ProtocolType(DatabaseModel): todos = relationship("Todo", backref=backref("protocoltype"), order_by="Todo.id") metas = relationship("DefaultMeta", backref=backref("protocoltype"), cascade="all, delete-orphan") - def __init__(self, name, short_name, organization, usual_time, - is_public, modify_group, private_group, public_group, - private_mail, public_mail, use_wiki, wiki_category, - wiki_only_public, printer, calendar, - restrict_networks, allowed_networks): - self.name = name - self.short_name = short_name - self.organization = organization - self.usual_time = usual_time - self.is_public = is_public - self.modify_group = modify_group - self.private_group = private_group - self.public_group = public_group - self.private_mail = private_mail - self.public_mail = public_mail - self.use_wiki = use_wiki - self.wiki_category = wiki_category - self.wiki_only_public = wiki_only_public - self.printer = printer - self.calendar = calendar - self.restrict_networks = restrict_networks - self.allowed_networks = allowed_networks - - def __repr__(self): - return ("<ProtocolType(id={}, short_name={}, name={}, " - "organization={}, is_public={}, modify_group={}, " - "private_group={}, public_group={}, use_wiki={}, " - "wiki_category='{}', wiki_only_public={}, printer={}, " - "usual_time={}, calendar='{}', restrict_networks={}, " - "allowed_networks='{}')>".format( - self.id, self.short_name, self.name, - self.organization, self.is_public, self.modify_group, - self.private_group, self.public_group, self.use_wiki, - self.wiki_category, self.wiki_only_public, self.printer, - self.usual_time, self.calendar, self.restrict_networks, - self.allowed_networks)) - def get_latest_protocol(self): candidates = sorted([protocol for protocol in self.protocols if protocol.is_done()], key=lambda p: p.date, reverse=True) if len(candidates) == 0: @@ -179,27 +152,13 @@ class Protocol(DatabaseModel): errors = relationship("Error", backref=backref("protocol"), cascade="all, delete-orphan", order_by="Error.id") metas = relationship("Meta", backref=backref("protocol"), cascade="all, delete-orphan") - def __init__(self, protocoltype_id, date, source=None, content_public=None, content_private=None, start_time=None, end_time=None, done=False, public=False): - self.protocoltype_id = protocoltype_id - self.date = date - self.source = source - self.content_private = content_private - self.content_public = content_public - self.start_time = start_time - self.end_time = end_time - self.done = done - self.public = public - - def __repr__(self): - return "<Protocol(id={}, protocoltype_id={})>".format( - self.id, self.protocoltype_id) - def get_parent(self): return self.protocoltype def create_error(self, action, name, description): now = datetime.now() - return Error(self.id, action, name, now, description) + return Error(protocol_id=self.id, action=action, name=name, + datetime=now, description=description) def fill_from_remarks(self, remarks): def _date_or_lazy(key, get_date=False, get_time=False): @@ -329,15 +288,6 @@ class DefaultTOP(DatabaseModel): name = db.Column(db.String) number = db.Column(db.Integer) - def __init__(self, protocoltype_id, name, number): - self.protocoltype_id = protocoltype_id - self.name = name - self.number = number - - def __repr__(self): - return "<DefaultTOP(id={}, protocoltype_id={}, name={}, number={})>".format( - self.id, self.protocoltype_id, self.name, self.number) - def get_parent(self): return self.protocoltype @@ -354,17 +304,6 @@ class TOP(DatabaseModel): planned = db.Column(db.Boolean) description = db.Column(db.String) - def __init__(self, protocol_id, name, number, planned, description=None): - self.protocol_id = protocol_id - self.name = name - self.number = number - self.planned = planned - self.description = description if description is not None else "" - - def __repr__(self): - return "<TOP(id={}, protocol_id={}, name={}, number={}, planned={})>".format( - self.id, self.protocol_id, self.name, self.number, self.planned) - def get_parent(self): return self.protocol @@ -378,17 +317,6 @@ class Document(DatabaseModel): is_compiled = db.Column(db.Boolean) is_private = db.Column(db.Boolean) - def __init__(self, protocol_id, name, filename, is_compiled, is_private): - self.protocol_id = protocol_id - self.name = name - self.filename = filename - self.is_compiled = is_compiled - self.is_private = is_private - - def __repr__(self): - return "<Document(id={}, protocol_id={}, name={}, filename={}, is_compiled={}, is_private={})>".format( - self.id, self.protocol_id, self.name, self.filename, self.is_compiled, self.is_private) - def get_parent(self): return self.protocol @@ -414,15 +342,6 @@ class DecisionDocument(DatabaseModel): name = db.Column(db.String) filename = db.Column(db.String) - def __init__(self, decision_id, name, filename): - self.decision_id = decision_id - self.name = name - self.filename = filename - - def __repr__(self): - return "<DecisionDocument(id={}, decision_id={}, name={}, filename={})>".format( - self.id, self.decision_id, self.name, self.filename) - def get_parent(self): return self.decision @@ -530,18 +449,6 @@ class Todo(DatabaseModel): protocols = relationship("Protocol", secondary="todoprotocolassociations", backref="todos") - def __init__(self, type_id, who, description, state, date, number=None): - self.protocoltype_id = type_id - self.number = number - self.who = who - self.description = description - self.state = state - self.date = date - - def __repr__(self): - return "<Todo(id={}, number={}, who={}, description={}, state={}, date={})>".format( - self.id, self.number, self.who, self.description, self.state, self.date) - def get_parent(self): return self.protocoltype @@ -628,14 +535,6 @@ class Decision(DatabaseModel): document = relationship("DecisionDocument", backref=backref("decision"), cascade="all, delete-orphan", uselist=False) - def __init__(self, protocol_id, content): - self.protocol_id = protocol_id - self.content = content - - def __repr__(self): - return "<Decision(id={}, protocol_id={}, content='{}')>".format( - self.id, self.protocol_id, self.content) - def get_parent(self): return self.protocol @@ -649,17 +548,6 @@ class MeetingReminder(DatabaseModel): send_private = db.Column(db.Boolean) additional_text = db.Column(db.String) - def __init__(self, protocoltype_id, days_before, send_public, send_private, additional_text): - self.protocoltype_id = protocoltype_id - self.days_before = days_before - self.send_public = send_public - self.send_private = send_private - self.additional_text = additional_text - - def __repr__(self): - return "<MeetingReminder(id={}, protocoltype_id={}, days_before={}, send_public={}, send_private={})>".format( - self.id, self.protocoltype_id, self.days_before, self.send_public, self.send_private) - def get_parent(self): return self.protocoltype @@ -673,17 +561,6 @@ class Error(DatabaseModel): datetime = db.Column(db.DateTime) description = db.Column(db.String) - def __init__(self, protocol_id, action, name, datetime, description): - self.protocol_id = protocol_id - self.action = action - self.name = name - self.datetime = datetime - self.description = description - - def __repr__(self): - return "<Error(id={}, protocol_id={}, action={}, name={}, datetime={})>".format( - self.id, self.protocol_id, self.action, self.name, self.datetime) - def get_parent(self): return self.protocol @@ -700,14 +577,6 @@ class TodoMail(DatabaseModel): name = db.Column(db.String, unique=True) mail = db.Column(db.String) - def __init__(self, name, mail): - self.name = name - self.mail = mail - - def __repr__(self): - return "<TodoMail(name='{}', mail='{}')>".format( - self.name, self.mail) - def get_formatted_mail(self): return "{} <{}>".format(self.name, self.mail) @@ -720,17 +589,6 @@ class OldTodo(DatabaseModel): description = db.Column(db.String) protocol_key = db.Column(db.String) - def __init__(self, old_id, who, description, protocol_key): - self.old_id = old_id - self.who = who - self.description = description - self.protocol_key = protocol_key - - def __repr__(self): - return ("<OldTodo(id={}, old_id={}, who='{}', description='{}', " - "protocol={}".format(self.id, self.old_id, self.who, - self.description, self.protocol_key)) - class DefaultMeta(DatabaseModel): __tablename__ = "defaultmetas" __model_name__ = "defaultmeta" @@ -739,15 +597,6 @@ class DefaultMeta(DatabaseModel): key = db.Column(db.String) name = db.Column(db.String) - def __init__(self, protocoltype_id, key, name): - self.protocoltype_id = protocoltype_id - self.key = key - self.name = name - - def __repr__(self): - return ("<DefaultMeta(id={}, protocoltype_id={}, key='{}', " - "name='{}')>".format(self.id, self.protocoltype_id, self.key)) - def get_parent(self): return self.protocoltype @@ -759,15 +608,6 @@ class Meta(DatabaseModel): name = db.Column(db.String) value = db.Column(db.String) - def __init__(self, protocol_id, name, value): - self.protocol_id = protocol_id - self.name = name - self.value = value - - def __repr__(self): - return "<Meta(id={}, protocoltype_id={}, name={}, value={})>".format( - self.id, self.protocoltype_id, self.name, self.value) - def get_parent(self): return self.protocol diff --git a/server.py b/server.py index 94b848935f51f514883ea16bdcefbdb27d254f82..aab9476a6621965a3b7a1b6f694188ba4306f3ef 100755 --- a/server.py +++ b/server.py @@ -208,14 +208,8 @@ def new_type(): if form.private_group.data not in user.groups: flash("Du kannst keinen internen Protokolltypen anlegen, zu dem du selbst keinen Zugang hast.", "alert-error") else: - protocoltype = ProtocolType(form.name.data, form.short_name.data, - form.organization.data, form.usual_time.data, form.is_public.data, - form.modify_group.data, form.private_group.data, form.public_group.data, - form.private_mail.data, form.public_mail.data, - form.use_wiki.data, form.wiki_category.data, - form.wiki_only_public.data, form.printer.data, - form.calendar.data, form.restrict_networks.data, - form.allowed_networks.data) + protocoltype = ProtocolType() + form.populate_obj(protocoltype) db.session.add(protocoltype) db.session.commit() flash("Der Protokolltyp {} wurde angelegt.".format(protocoltype.name), "alert-success") @@ -268,7 +262,8 @@ def delete_type(protocoltype): def new_reminder(protocoltype): form = MeetingReminderForm() if form.validate_on_submit(): - meetingreminder = MeetingReminder(protocoltype.id, form.days_before.data, form.send_public.data, form.send_private.data, form.additional_text.data) + meetingreminder = MeetingReminder(protocoltype_id=protocoltype.id) + form.populate_obj(meetingreminder) db.session.add(meetingreminder) db.session.commit() return redirect(request.args.get("next") or url_for("show_type", protocoltype_id=protocoltype.id)) @@ -303,7 +298,8 @@ def delete_reminder(meetingreminder): def new_default_top(protocoltype): form = DefaultTopForm() if form.validate_on_submit(): - defaulttop = DefaultTOP(protocoltype.id, form.name.data, form.number.data) + defaulttop = DefaultTOP(protocoltype_id=protocoltype.id) + form.populate_obj(defaulttop) db.session.add(defaulttop) db.session.commit() flash("Der Standard-TOP {} wurde für dem Protokolltyp {} hinzugefügt.".format(defaulttop.name, protocoltype.name), "alert-success") @@ -447,11 +443,12 @@ def new_protocol(): upload_form = NewProtocolSourceUploadForm(protocoltypes) file_upload_form = NewProtocolFileUploadForm(protocoltypes) if form.validate_on_submit(): - protocoltype = ProtocolType.query.filter_by(id=form.protocoltype.data).first() + protocoltype = ProtocolType.query.filter_by(id=form.protocoltype_id.data).first() if protocoltype is None or not protocoltype.has_modify_right(user): flash("Dir fehlen die nötigen Zugriffsrechte.", "alert-error") return redirect(request.args.get("next") or url_for("index")) - protocol = Protocol(protocoltype.id, form.date.data) + protocol = Protocol(protocoltype_id=protocoltype.id) + form.populate_obj(protocol) db.session.add(protocol) db.session.commit() tasks.push_tops_to_calendar(protocol) @@ -544,11 +541,11 @@ def upload_new_protocol(): flash("Es wurde keine Datei ausgewählt.", "alert-error") return redirect(request.args.get("fail") or url_for("new_protocol")) source = file.stream.read().decode("utf-8") - protocoltype = ProtocolType.query.filter_by(id=form.protocoltype.data).first() + protocoltype = ProtocolType.query.filter_by(id=form.protocoltype_id.data).first() if protocoltype is None or not protocoltype.has_modify_right(user): flash("Invalider Protokolltyp oder keine Rechte.", "alert-error") return redirect(request.args.get("fail") or url_for("new_protocol")) - protocol = Protocol(protocoltype.id, None, source) + protocol = Protocol(protocoltype_id=protocoltype.id, source=source) db.session.add(protocol) db.session.commit() tasks.parse_protocol(protocol) @@ -570,14 +567,16 @@ def upload_new_protocol_by_file(): flash("Es wurde keine Datei ausgewählt.", "alert-error") return redirect(request.args.get("fail") or url_for("new_protocol")) filename = secure_filename(file.filename) - protocoltype = ProtocolType.query.filter_by(id=form.protocoltype.data).first() + protocoltype = ProtocolType.query.filter_by(id=form.protocoltype_id.data).first() if protocoltype is None or not protocoltype.has_modify_right(user): flash("Invalider Protokolltyp oder keine Rechte.", "alert-error") return redirect(request.args.get("fail") or url_for("new_protocol")) - protocol = Protocol(protocoltype.id, datetime.now().date(), done=True) + protocol = Protocol(protocoltype_id=protocoltype.id, date=datetime.now().date(), done=True) db.session.add(protocol) db.session.commit() - document = Document(protocol.id, filename, "", False, form.private.data) + document = Document(protocol_id=protocol.id, name=filename, + filename="", is_compiled=False) + form.populate_obj(document) db.session.add(document) db.session.commit() internal_filename = "{}-{}-{}".format(protocol.id, document.id, filename) @@ -666,7 +665,8 @@ def send_protocol(protocol): def new_top(protocol): form = TopForm() if form.validate_on_submit(): - top = TOP(protocol_id=protocol.id, name=form.name.data, number=form.number.data, planned=True, description=form.description.data) + top = TOP(protocol_id=protocol.id, planned=True) + form.populate_obj(top) db.session.add(top) db.session.commit() tasks.push_tops_to_calendar(top.protocol) @@ -792,9 +792,8 @@ def new_todo(): if added_protocoltype is None or not added_protocoltype.has_modify_right(user): flash("Invalider Protokolltyp.") return redirect(request.args.get("next") or url_for("index")) - todo = Todo(type_id=form.protocoltype_id.data, who=form.who.data, - description=form.description.data, tags=form.tags.data, - done=form.done.data) + todo = Todo() + form.populate_obj(todo) if protocol is not None: todo.protocols.append(protocol) db.session.add(todo) @@ -937,7 +936,9 @@ def upload_document(protocol): # todo: Dateitypen einschränken? if file: filename = secure_filename(file.filename) - document = Document(protocol.id, filename, "", False, form.private.data) + document = Document(protocol_id=protocol.id, name=filename, + filename="", is_compiled=False) + form.populate_obj(document) db.session.add(document) db.session.commit() internal_filename = "{}-{}-{}".format(protocol.id, document.id, filename) @@ -1028,7 +1029,8 @@ def list_todomails(): def new_todomail(): form = TodoMailForm() if form.validate_on_submit(): - todomail = TodoMail(form.name.data, form.mail.data) + todomail = TodoMail() + form.populate_obj(todomail) db.session.add(todomail) db.session.commit() flash("Die Todomailzuordnung für {} wurde angelegt.".format(todomail.name), "alert-success") @@ -1064,8 +1066,8 @@ def delete_todomail(todomail): def new_defaultmeta(protocoltype): form = DefaultMetaForm() if form.validate_on_submit(): - meta = DefaultMeta(protocoltype_id=protocoltype.id, key=form.key.data, - name=form.name.data) + meta = DefaultMeta(protocoltype_id=protocoltype.id) + form.populate_obj(meta) db.session.add(meta) db.session.commit() flash("Metadatenfeld hinzugefügt.", "alert-success") diff --git a/tasks.py b/tasks.py index 650eaa881986a0d45f8c397e9f430354954c11a1..18527844de3a3b909da09c3c89cf911025b815d8 100644 --- a/tasks.py +++ b/tasks.py @@ -235,7 +235,7 @@ def parse_protocol_async_inner(protocol, encoded_kwargs): db.session.commit() return if todo is None and field_id is None and what in old_todo_number_map: - todo = Todo(type_id=protocol.protocoltype.id, + todo = Todo(protocoltype_id=protocol.protocoltype.id, who=who, description=what, state=field_state, date=field_date, number=old_todo_number_map[what]) db.session.add(todo) @@ -246,7 +246,7 @@ def parse_protocol_async_inner(protocol, encoded_kwargs): OldTodo.protocol_key == protocol_key).all() if len(old_candidates) == 0: # new protocol - todo = Todo(type_id=protocol.protocoltype.id, + todo = Todo(protocoltype_id=protocol.protocoltype.id, who=who, description=what, state=field_state, date=field_date) db.session.add(todo) @@ -258,7 +258,7 @@ def parse_protocol_async_inner(protocol, encoded_kwargs): number = field_id or lookup_todo_id(old_candidates, who, what) todo = Todo.query.filter_by(number=number).first() if todo is None: - todo = Todo(type_id=protocol.protocoltype.id, + todo = Todo(protocoltype_id=protocol.protocoltype.id, who=who, description=what, state=field_state, date=field_date, number=number) db.session.add(todo) @@ -295,7 +295,8 @@ def parse_protocol_async_inner(protocol, encoded_kwargs): protocol.tops.remove(top) tops = [] for index, fork in enumerate((child for child in tree.children if isinstance(child, Fork))): - top = TOP(protocol.id, fork.name, index, False) + top = TOP(protocol_id=protocol.id, name=fork.name, number=index, + planned=False) db.session.add(top) db.session.commit() @@ -383,9 +384,21 @@ def compile_async(content, protocol_id, show_private=False, use_decision=False, for old_document in [document for document in protocol.documents if document.is_compiled and document.is_private == show_private]: protocol.documents.remove(old_document) db.session.commit() - document = Document(protocol.id, name="protokoll{}_{}_{}.pdf".format("_intern" if show_private else "", protocol.protocoltype.short_name, date_filter_short(protocol.date)), filename="", is_compiled=True, is_private=show_private) + document = Document(protocol_id=protocol.id, + name="protokoll{}_{}_{}.pdf".format( + "_intern" if show_private else "", + protocol.protocoltype.short_name, + date_filter_short(protocol.date)), + filename="", + is_compiled=True, + is_private=show_private) else: - document = DecisionDocument(decision.id, name="beschluss_{}_{}_{}.pdf".format(protocol.protocoltype.short_name, date_filter_short(protocol.date), decision.id), filename="") + document = DecisionDocument(decision_id=decision.id, + name="beschluss_{}_{}_{}.pdf".format( + protocol.protocoltype.short_name, + date_filter_short(protocol.date), + decision.id), + filename="") db.session.add(document) db.session.commit() target_filename = "compiled-{}-{}.pdf".format(document.id, "internal" if show_private else "public") diff --git a/templates/protocol-tops-include.html b/templates/protocol-tops-include.html index ac27c6fbb2052abd1b5a0ae8123f10667e065782..93a962ae0f0c4f6a9d4e9cc60d8630c73c9fb507 100644 --- a/templates/protocol-tops-include.html +++ b/templates/protocol-tops-include.html @@ -7,7 +7,7 @@ {% endfor %} {% endif %} {% for top in protocol.tops %} - <li{% if has_private_view_right %} class="expansion-button" id="top-{{top.id}}" title="{{top.description}}"{% endif %}> + <li{% if has_private_view_right and top.description is not none %} class="expansion-button" id="top-{{top.id}}" title="{{top.description}}"{% endif %}> {{top.name}} {% if not protocol.is_done() and has_modify_right %} ({{top.number}}) @@ -18,7 +18,7 @@ <a href="{{url_for('move_top', top_id=top.id, diff=-1)}}">Hoch</a> <a href="{{url_for('delete_top', top_id=top.id)}}" onclick="return confirm('Bist du dir sicher, dass du den TOP {{top.name}} löschen möchtest?');">Löschen</a> {% endif %} - {% if has_private_view_right and top.description|length > 0 %} + {% if has_private_view_right and top.description is not none and top.description|length > 0 %} <span class="glyphicon glyphicon-info-sign"></span> <pre id="top-{{top.id}}-description" class="expansion-text"> {{-top.description-}} diff --git a/views/forms.py b/views/forms.py index ffc9ce634d4058ccdbd09d736cb85887be7b7ab6..4f57cc266202cb4f32be297b44944369520538f3 100644 --- a/views/forms.py +++ b/views/forms.py @@ -133,12 +133,12 @@ class MeetingReminderForm(FlaskForm): additional_text = TextAreaField("Zusätzlicher Mailinhalt") class NewProtocolForm(FlaskForm): - protocoltype = SelectField("Typ", choices=[], coerce=int) + protocoltype_id = SelectField("Typ", choices=[], coerce=int) date = DateField("Datum", validators=[InputRequired("Du musst ein Datum angeben.")], format="%d.%m.%Y") def __init__(self, protocoltypes, **kwargs): super().__init__(**kwargs) - self.protocoltype.choices = get_protocoltype_choices(protocoltypes, add_all=False) + self.protocoltype_id.choices = get_protocoltype_choices(protocoltypes, add_all=False) class DocumentUploadForm(FlaskForm): document = FileField("Datei") @@ -149,20 +149,20 @@ class KnownProtocolSourceUploadForm(FlaskForm): class NewProtocolSourceUploadForm(FlaskForm): source = FileField("Quellcode") - protocoltype = SelectField("Typ", choices=[], coerce=int) + protocoltype_id = SelectField("Typ", choices=[], coerce=int) def __init__(self, protocoltypes, **kwargs): super().__init__(**kwargs) - self.protocoltype.choices = get_protocoltype_choices(protocoltypes, add_all=False) + self.protocoltype_id.choices = get_protocoltype_choices(protocoltypes, add_all=False) class NewProtocolFileUploadForm(FlaskForm): file = FileField("Datei") - protocoltype = SelectField("Typ", choices=[], coerce=int) + protocoltype_id = SelectField("Typ", choices=[], coerce=int) private = BooleanField("Intern") def __init__(self, protocoltypes, **kwargs): super().__init__(**kwargs) - self.protocoltype.choices = get_protocoltype_choices(protocoltypes, add_all=False) + self.protocoltype_id.choices = get_protocoltype_choices(protocoltypes, add_all=False) class ProtocolForm(FlaskForm): date = DateField("Datum", validators=[InputRequired("Bitte gib das Datum des Protkolls an.")], format="%d.%m.%Y") diff --git a/views/tables.py b/views/tables.py index ff7ecd1408c3aca578cdcf8b287aa6a01296870b..cfa177f744bea9e1d416ea25b403e350512400e4 100644 --- a/views/tables.py +++ b/views/tables.py @@ -123,10 +123,13 @@ class ProtocolTypesTable(Table): has_private_view_right = protocoltype.has_private_view_right(user) has_modify_right = protocoltype.has_modify_right(user) protocoltype_link = url_for("show_type", protocoltype_id=protocoltype.id) - protocol_link = url_for("show_protocol", protocol_id=protocol.id) + protocol_link = (url_for("show_protocol", protocol_id=protocol.id) + if protocol is not None else "") new_protocol_link = url_for("new_protocol", protocoltype_id=protocoltype.id) mobile_name = "{} ({})".format(protocoltype.name, protocoltype.short_name) - mobile_links = [Table.link(protocol_link, protocol.get_identifier())] + mobile_links = [] + if protocol is not None: + mobile_links.append(Table.link(protocol_link, protocol.get_identifier())) if has_modify_right: mobile_links.append(Table.link(new_protocol_link, "Neues Protokoll")) mobile_part = [