Contact
*******
.. highlight:: python
The new version of the contact app (branch ``2953-ember``) stores multiple email
addresses, phone numbers and postal addresses for each contact.
.. note:: The ``email`` address in the ``User`` is not indexed by ElasticSearch.
All email addresses should be stored in the ``ContactEmail`` model
(migration 0006_auto_20180417_0736_ handles this automatically).
Icon
====
::
Management Commands
===================
::
rebuild_contact_index
refresh_contact_index
Model
=====
Define the contact model in ``settings/base.py`` (or in ``example_app/base.py``
for an app)::
CONTACT_MODEL = "contact.Contact"
To get the actual contact model, create a ``get_contact_model`` function
(perhaps in ``models.py``) e.g::
from django.apps import apps
from django.conf import settings
def get_contact_model():
return apps.get_model(settings.CONTACT_MODEL)
.. _contact-app-test-rest-framework-json-api:
REST Framework - JSON API
=========================
The contact app can be used to test the JSON API.
Create a ``data.json`` file e.g. :download:`misc/app-contact/data.json`
To test with ``httpie``::
pip install httpie
# list the contacts
http GET http://localhost:8000/api/0.1/contacts/
# create a contact
http POST http://localhost:8000/api/0.1/contacts/ Content-Type:'application/vnd.api+json' @data.json
To test with no authentication, comment out
``authentication_classes`` and ``permission_classes`` e.g:
.. code-block:: diff
--- a/contact/api.py
+++ b/contact/api.py
@@ -19,8 +19,8 @@ from .serializers import (
class SoftDeleteViewSet(viewsets.ModelViewSet):
"""An API view which marks records as deleted, rather than deleting them."""
- authentication_classes = (TokenAuthentication,)
- permission_classes = (IsAuthenticated,)
+ # authentication_classes = (TokenAuthentication,)
+ # permission_classes = (IsAuthenticated,)
Templates and Mixins
====================
.. tip:: All projects which use the ``contact`` app should provide a *detail*
URL named ``contact.detail``.
``ContactDetailMixin``
----------------------
::
from braces.views import LoginRequiredMixin, StaffuserRequiredMixin
from django.views.generic import DetailView, TemplateView
from contact.views import ContactDetailMixin
class ContactDetailView(
LoginRequiredMixin,
StaffuserRequiredMixin,
ContactDetailMixin,
BaseMixin,
DetailView,
):
pass
::
from .views import ContactDetailView
re_path(
r"^contact/(?P\d+)/$",
view=ContactDetailView.as_view(),
name="contact.detail",
),
``test_view_perm.py``::
from contact.tests.factories import UserContactFactory
@pytest.mark.django_db
def test_contact_detail(perm_check):
user_contact = UserContactFactory()
url = reverse("contact.detail", args=[user_contact.contact.pk])
perm_check.staff(url)
.. tip:: The ``example_contact/templates/example/contact_detail.html`` example
template shows an example of how to use the two contact detail views::
{% include 'contact/contact_detail.html' %}
{% include 'contact/contact_detail_multi.html' %}
``ContactListMixin``
--------------------
::
from contact.views import ContactListMixin
class ContactListView(
LoginRequiredMixin,
StaffuserRequiredMixin,
ContactListMixin,
BaseMixin,
ListView,
):
template_name = "example/contact_list.html"
.. tip:: We also have a ``contact/templates/contact/_contact_list.html`` which
can be included in your own templates if required::
{% include 'contact/_contact_list.html' %}
::
re_path(
r"^contact/$",
view=ContactListView.as_view(),
name="contact.list"
),
::
@pytest.mark.django_db
def test_contact_list(perm_check):
url = reverse("contact.list")
perm_check.staff(url)
.. _user_contact_redirect_view:
``UserContactRedirectView``
---------------------------
This is a standard view which redirects from a user ``pk`` to a contact detail
view. It is used by the ``app-gdpr``.
::
from django.views.generic import RedirectView
class UserContactRedirectView(RedirectView):
permanent = False
def get_redirect_url(self, *args, **kwargs):
pk = kwargs["user_pk"]
contact = Contact.objects.get(user__pk=pk)
return reverse("contact.detail", args=[contact.pk])
::
from .views import UserContactRedirectView
re_path(
r"^user/(?P\d+)/redirect/$",
view=UserContactRedirectView.as_view(),
name="user.redirect.contact",
),
Search
======
To create a simple contact search::
from contact.search import ContactIndex
from search.views import SearchViewMixin
class SearchView(LoginRequiredMixin, StaffuserRequiredMixin, SearchViewMixin):
INDEX_CHOICES = (("contact", "Contact"),)
INDEX_CLASSES = {"contact": ContactIndex}
::
re_path(
r"^example/search/$",
view=SearchView.as_view(),
name="project.search",
),
.. tip:: This is using the standard URL name for a site wide search i.e.
``project.search``.
.. _0006_auto_20180417_0736: https://gitlab.com/kb/contact/blob/2953-ember/contact/migrations/0006_auto_20180417_0736.py