Skip to content

Code improvement feedback app#1672

Open
vanlummelhuizen wants to merge 16 commits intomasterfrom
code-improvement-feedback-app
Open

Code improvement feedback app#1672
vanlummelhuizen wants to merge 16 commits intomasterfrom
code-improvement-feedback-app

Conversation

@vanlummelhuizen
Copy link
Collaborator

@vanlummelhuizen vanlummelhuizen commented Dec 11, 2025

This is an attempt at making the code of the feedback app more clean, DRY-er, easier to read and to maintain. Please let me know what you think.

@vanlummelhuizen vanlummelhuizen marked this pull request as ready for review December 11, 2025 09:32
@Woseseltops Woseseltops requested a review from Copilot December 11, 2025 12:57
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This pull request refactors the feedback app to improve code quality, reduce duplication, and enhance maintainability. The changes consolidate repetitive view logic, simplify control flow patterns, and modernize code conventions.

Key changes:

  • Introduced a generic_showfeedback helper function to eliminate duplicated permission checking and rendering logic across multiple views
  • Refactored recordsignfeedback to handle both glosses and morphemes through a single code path using an is_morpheme parameter
  • Simplified form handling patterns by inverting conditionals (checking for POST early and returning)

Reviewed changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
signbank/feedback/views.py Core refactoring: consolidated duplicate view logic, simplified control flow with early returns, modernized string formatting to f-strings
signbank/feedback/urls.py Cleaned up imports by removing unused dependencies
signbank/feedback/templates/feedback/show_feedback_signs.html Fixed display of sign languages to properly iterate and comma-separate values
signbank/feedback/models.py Reorganized imports, simplified conditional expressions, removed unused __init__ method, updated to modern super() syntax
signbank/feedback/admin.py Minor formatting cleanup removing extra blank lines

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

return render(request, template_name, context)


def generic_showfeedback(request: QueryDict, extra_context: dict, template_name: str) -> HttpResponse:
Copy link

Copilot AI Dec 11, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The request parameter should be typed as HttpRequest, not QueryDict. QueryDict is the type for request.GET and request.POST, not the request object itself.

Copilot uses AI. Check for mistakes.
extra_context = {'morphfb': (MorphemeFeedback.objects
.filter(morpheme__lemma__dataset__in=get_selected_datasets(request))
.filter(status__in=('unread', 'read')))}
return generic_showfeedback(request, extra_context,"feedback/show_feedback_morphemes.html")
Copy link

Copilot AI Dec 11, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing space after comma before the template name argument.

Copilot uses AI. Check for mistakes.
else:
gloss = get_object_or_404(Gloss, id=glossid, archived=False)
return recordsignfeedback(request, glossid)
return recordsignfeedback(request, glossid, is_morpheme=False)
Copy link

Copilot AI Dec 11, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The parameter name glossid is inconsistent with the updated function signature which uses id. Consider renaming the parameter in glossfeedback and morphemefeedback to id for consistency.

Copilot uses AI. Check for mistakes.
value = request.POST.get('value', '')

(what, fbid) = field.split('_')
_, id = field.split('_')
Copy link

Copilot AI Dec 11, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The variable id shadows the function parameter with the same name. Use a different name like feedback_id to avoid confusion.

Copilot uses AI. Check for mistakes.

def __init__(self, *args, **kwargs):
super(SignFeedbackForm, self).__init__(*args, **kwargs)
super().__init__(*args, **kwargs)
Copy link

Copilot AI Dec 11, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The MorphemeFeedbackForm.__init__ method was removed, but it should be retained if there's any initialization logic needed for consistency with other form classes. If truly unnecessary, this is fine.

Copilot uses AI. Check for mistakes.
@susanodd
Copy link
Collaborator

susanodd commented Dec 15, 2025

A lot of improvements. The original code was very weird, especially now seeing it next to the new code.
The additions of expression conditionals instead of if-else branching on empty values improves the code a lot.
It's great those weird "values" with the ids in the forms have been removed!

  • The method with country and language,

def t(message):
"""Replace $country and $language in message with dat from settings"""
tpl = string.Template(message)
return tpl.substitute(country=settings.COUNTRY_NAME, language=settings.LANGUAGE_NAME)

Is this being used for the feedback?

The code runs great! It looks like users have been using the feedback!

Just that question about that function.

I can't get the review thing to work for me. It won't let me comment in specific places.

Copy link
Collaborator

@Woseseltops Woseseltops left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for cleaning up! Almost 200 lines of code less with the same functionality must be a great improvement to maintainability :)

</div>
<form action="{{PREFIX_URL}}/feedback/missingsign/delete/{{fb.pk}}" method='post'>
{% csrf_token %}
<input type='hidden' name='id' value='deletefeedbackmissingn_{{fb.pk}}'>
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are you sure this doesn't do anything? I would guess this is an essential parameter to communicate which feedback needs deleting.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The ID of the Feedback instance that is to be deleted, is send through the url in the form action. As far as I can tell the hidden input is never used in

def delete(request, kind, id):
"""Mark a feedback item as deleted, kind 'signfeedback', 'generalfeedback' or 'missingsign'"""
url = request.META.get('HTTP_REFERER', '/')
kinds = {
'sign': SignFeedback,
'morpheme': MorphemeFeedback,
'general': GeneralFeedback,
'missingsign': MissingSignFeedback
}
if kind not in kinds:
return redirect(url)
model = kinds[kind]
if request.POST.get('value', '') == 'confirmed':
item = get_object_or_404(model, pk=id)
item.status = 'deleted'
item.save()
return redirect(url)

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, I couldn't find it either.

Comment on lines +89 to +97
missing_sign_feedback = MissingSignFeedback(user=request.user)
if 'signlanguage' in form.cleaned_data:
missing_sign_feedback.signlanguage = form.cleaned_data['signlanguage']
if 'video' in form.cleaned_data and form.cleaned_data['video'] is not None:
missing_sign_feedback.video = form.cleaned_data['video']
if 'sentence' in form.cleaned_data and form.cleaned_data['sentence'] is not None:
missing_sign_feedback.sentence = form.cleaned_data['sentence']
missing_sign_feedback.meaning = form.cleaned_data['meaning']
missing_sign_feedback.comments = form.cleaned_data['comments']
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How about

cleaned_data = form.cleaned_data
missing_sign_feedback = MissingSignFeedback(
    user=request.user,
    meaning=cleaned_data['meaning'],
    comments=cleaned_data['comments'],
    signlanguage=cleaned_data.get('signlanguage'),
    video=cleaned_data.get('video'),
    sentence=cleaned_data.get('sentence')
)

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since the fields signlanguage, video and sentence can handle None as input (I checked), this should also work. It is a nice improvement. I will apply it.

@susanodd
Copy link
Collaborator

susanodd commented Jan 16, 2026

This is the comments for my review. Not sure if you looked at these.

@vanlummelhuizen can you check this code?

def t(message):
"""Replace $country and $language in message with dat from settings"""
tpl = string.Template(message)
return tpl.substitute(country=settings.COUNTRY_NAME, language=settings.LANGUAGE_NAME)

Can the above be deleted from the feedback?

I'm working on the communication emails and there is a context variable that uses settings.LANGUAGE_NAME and in the emails it ends up ultimately as "Global Signbank" (as the result of evaluating the context variables)

signbank/settings/server_specific/default.py:LANGUAGE_NAME = 'Global'
signbank/settings/server_specific/asl_yale.py:LANGUAGE_NAME = "ASL"

As well as other that use code:

current_site = Site.objects.get_current()

This is actually WRONG, it yields:

signbank.science.ru.nl

(from the database)

So the wrong thing is ending up in the emails...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants