Package: django-feedback-govuk
django-feedbackA Django app to gather and send internal Government staff feedback, e.g. for open beta periodsInstallationpip install django-feedback-govukAdddjango-feedbackto your INSTALLED_APPS settings:INSTALLED_APPS=[...'crispy_forms','crispy_forms_gds','django_feedback_govuk',...]Create a new email template in the GovUk Notify service, making sure to create a ((feedback_url)) field.Note that ((feedback_url)) will be a link to the listing view, not an individual piece of feedback.You'll need an API key and template ID from the gov.uk Notify service.Add the following settings to the file:# Crispy formsCRISPY_ALLOWED_TEMPLATE_PACKS=["gds"]CRISPY_TEMPLATE_PACK="gds"# Django Feedback GovUKDJANGO_FEEDBACK_GOVUK={"SERVICE_NAME":"<your-service>","COPY":{#...add any copy tags to override here},"FEEDBACK_FORMS":{"default":{"model":"django_feedback_govuk.models.Feedback","form":"django_feedback_govuk.forms.FeedbackForm","view":"django_feedback_govuk.views.FeedbackView",},# ...add extra feedback forms here],}The copy dict contains string IDs for all user-facing copy, defaulting to the following (override
just the fields you want to, using the{{ service_name }}variable if necessary for _title and _body strings):{"SUBMIT_TITLE":"Give feedback on {{ service_name }}","CONFIRM_TITLE":"Feedback submitted","CONFIRM_BODY":"Thank you for submitting your feedback.","FIELD_SATISFACTION_LEGEND":"Overall, how did you feel about the service you received today?","FIELD_COMMENT_LEGEND":"How could we improve this service?","FIELD_COMMENT_HINT":"Do not include any personal or financial information, for example your National Insurance or credit card numbers.",}The email addresses are for every recipient that should get an email when feedback is submitted.Build your own templatesOverride the built-in templates by making new templates in your app under thedjango_feedback_govuk/templatespath. You'll need templates forsubmit.html,confirm.html,listing.htmlandsubmitted.html, each of which should load its respective template tag fromfeedback_submit,feedback_confirm,feedback_listingandfeedback_submitted.For example:{# /your-project/templates/django_feedback_govuk/templates/submit.html #}{%extends"base.html"%}{%loadfeedback_tags%}{%blockcontent%}{%feedback_submit%}{%endblockcontent%}If you'd like to use the templatetags without causing page loads to new viewsAdd the URLs to your projectfromdjango_feedback_govukimporturlsasfeedback_urlsurlpatterns=[...path("feedback/",include(feedback_urls)),...]Set up user permissionsAdding more/custom feedback formsTheFEEDBACK_FORMSkey in theDJANGO_FEEDBACK_GOVUKsettings dict can be used to add a custom feedback model with a custom form and optional view to allow different kinds of feedback to be submitted.Define your custom feedback model:Define a feedback model that inherits fromBaseFeedback.BaseFeedbackprovides thesubmitterandsubmitted_atfields and logic. Add any custom fields to store the submitted data.# models.pyfromdjango.dbimportmodelsfromdjango_feedback_govuk.modelsimportBaseFeedbackclassCustomFeedback(BaseFeedback):custom_field=models.TextField(blank=True)Define your custom model form:Define a model form that inherits fromBaseFeedbackForm.BaseFeedbackFormprovides the initial foundations for your feedback form. Simply, add your new model fields to theMeta.fieldslist and define the layout usingcrispy_forms_gds. Then move the submit button to the bottom of the layout.# forms.pyfromcrispy_forms_gds.layoutimportField,Fieldset,Sizefromdjango_feedback_govuk.formsimportSUBMIT_BUTTON,BaseFeedbackFormfrom.modelsimportCustomFeedbackclassCustomFeedbackForm(BaseFeedbackForm):classMeta:model=CustomFeedbackfields=["submitter","custom_field"]def__init__(self,*args,**kwargs):super().__init__(*args,**kwargs)self.fields["custom_field"].label=""self.helper.layout.remove(SUBMIT_BUTTON)self.helper.layout.append(Fieldset(Field("custom_field"),legend="Custom question?",legend_size=Size.MEDIUM,))self.helper.layout.append(SUBMIT_BUTTON)Update settingsAdd a new entry to theDJANGO_FEEDBACK_GOVUK["FEEDBACK_FORMS"]dict that tells the package where to find the new model and form, give it a unique key that gives some context to the purpose of the new feedback form.# settings.pyDJANGO_FEEDBACK_GOVUK={..."FEEDBACK_FORMS":{"default":{"model":"django_feedback_govuk.models.Feedback","form":"django_feedback_govuk.forms.FeedbackForm","view":"django_feedback_govuk.views.FeedbackView",},"custom":{"model":"YOUR_PACKAGE.models.CustomFeedback","form":"YOUR_PACKAGE.forms.CustomFeedbackForm",},],}Custom form copyYou can override the default copy passed to the forms by adding acopykey to theDJANGO_FEEDBACK_GOVUK["FEEDBACK_FORMS"][YOUR_FORM]dict like so:# settings.pyDJANGO_FEEDBACK_GOVUK={..."FEEDBACK_FORMS":{"default":{"model":"django_feedback_govuk.models.Feedback","form":"django_feedback_govuk.forms.FeedbackForm","view":"django_feedback_govuk.views.FeedbackView",},"custom":{"model":"YOUR_PACKAGE.models.CustomFeedback","form":"YOUR_PACKAGE.forms.CustomFeedbackForm","copy":{"SUBMIT_TITLE":"Please provide feedback on {{ service_name }}",},},},}This copy dict should match the formatting of the rootCOPYdict. However, it can't override the copy that is defined on the providedFeedbackForm. If you wish to use that form in multiple feedback forms you should create a custom form that inherits fromFeedbackForm, and update the text there.Pushing to PyPIPyPI PackageTest PyPI PackageRunningmake build-packagewill build the package into thedist/directory.Runningmake push-pypi-testwill push the built package to Test PyPI.Runningmake push-pypiwill push the built package to PyPI.Setting up poetry for pushing to PyPIFirst you will need to add the test pypy repository to your poetry config:poetry config repositories.test-pypi https://test.pypi.org/legacy/Then go tohttps://test.pypi.org/manage/account/token/and generate a token.Then add it to your poetry config:poetry config pypi-token.test-pypi XXXXXXXXThen you also need to go tohttps://pypi.org/manage/account/token/to generate a token for the real PyPI.Then add it to your poetry config:poetry config pypi-token.pypi XXXXXXXXNow the make commands should work as expected.Sending automated emails after form submissionBased on the needs of your project you may want to be notified of the feedback received. For example you might want to receive an email if there is new feedback to be reviewed. To do this you can create a method and call it on a regular schedule (e.g. once a day) through cron, Celery Beat, etc.feedback_submitted_past_day = (
    BaseFeedback.objects.all().filter(
        submitted_at__gte=timezone.now() + timedelta(days=-1),
    ).exists()
)
if feedback_submitted_past_day:
    send_email() # This is not a real method, just an example to show this is where the send email logic would go.This can be achieved through theGovUK NotifyClient.