Теги: contact django python

Список контактов пользователя.

Бекенд.

Модель данных.

Создадим приложение под контакты и включим его в INSTALLED_APPS.

./manage.py startapp contact


INSTALLED_APPS = [
   ...
    'contact'
]

Создадим модель под список контактов (backend/contact/models.py) и проведем миграцию.

from django.db import models
from account.models import UserProfile
from chat.models import ChatRoom

class Contact(models.Model):
    owner = models.ForeignKey(UserProfile, on_delete=models.CASCADE, related_name='owner')
    contact_user = models.ForeignKey(UserProfile, on_delete=models.CASCADE, related_name='contact_user')
    room = models.ForeignKey(ChatRoom, on_delete=models.CASCADE)

Создадим серилизатор backend/contact/serializers/contact.py

from rest_framework import serializers

from account.serializers.profile import UserProfileSerializer
from chat.serializers.room import ChatRoomSerializer
from contact.models import Contact

class ContactSerializer(serializers.ModelSerializer):
    contact_user = UserProfileSerializer(read_only=True)
    room_token = serializers.SerializerMethodField()


    def get_room_token(self, obj):
        return obj.room.token


    class Meta:
        model = Contact
        fields = [
            'room_token',
            'owner',
            'contact_user',
            'id'
        ]

Создадим представление backend/contact/views/contact.py.

from rest_framework.permissions import IsAuthenticated
from rest_framework.response import Response
from rest_framework import generics

from contact.serializers.contact import ContactSerializer
from contact.models import Contact

class ContactListView(generics.ListAPIView):
    '''

    Get the contact list of the user.


    '''
    serializer_class = ContactSerializer
    queryset = Contact.objects.all().order_by('-id')

Дочерний роутинг backend/contact/urls.py

from django.urls import path, include
from contact.views.contact import ContactListView

urlpatterns = [

    path('list/',ContactListView.as_view()),
]

Включаем в глобальный роутинг backend/backend/urls.py.

path('v1/',include([
    ...
    path('contact/',include('contact.urls'))
])),

Добавим булевый флаг в модель чат-комнат has_contact, и если он равен False будем в отдельном методе проверять наличие сообщений от двух пользователей комнаты.

Т.е. если пользователь получает ответ от оппонента, создается запись в таблице контактов.

Причем по 2 записи для каждого пользователя по одной c пользователем в поле owner.

class ChatRoom(models.Model):
    ...
    has_contact = models.BooleanField(default=False)

    def get_opponent(self,user):
        for u in self.get_participants():
            if u != user:
                return u

    def check_contact(self):
        if not self.has_contact:
            cnt = []
            for user in self.get_participants():
                cnt.append(ChatMessage.objects.filter(user=user).count())
            if 0 not in cnt:
                self.has_contact = True
                self.save()
                for user in self.get_participants():
                    Contact.objects.create(owner=user, \
                        room=self, \
                        contact_user=self.get_opponent(user))

Осталось вызвать метод check_contact из представления just-dating/backend/chat/views/message.py.

class CreateRoomMessageView(generics.CreateAPIView):
    ....

    def perform_create(self, serializer):
        room = ChatRoom.objects.get(token=serializer.validated_data['token'])
        serializer.save(user=self.request.user.userprofile, room=room)
        room.check_contact()

Посылаем сообщение в центрифугу.

Подцепимся на процесс создания объекта Contact и отправим сообщение в пользовательский калал центрифуги backend/contact/models.py.

...
from django.db.models.signals import post_save
from django.dispatch import receiver
from backend.cent_client import CentClient
from rest_framework.authtoken.models import Token

...


class Contact(models.Model):
   ...

@receiver(post_save, sender=Contact)
def send_contact_message_created(sender, instance, created, **kwargs):
    from contact.serializers.contact import ContactSerializer
    if created:
        cent_client = CentClient()
        token, created = Token.objects.get_or_create(user=instance.owner)
        payload =  { \
                    'type': 'contact_created_message', \
                    'message': ContactSerializer(instance).data \
                    }     
        cent_client.send(token.key, payload)

Доделаем команду загрузки тестовых данных в чат и аналогичным обзам отправим сообщения-ответ от женщин backend/chat/management/commands/load_chat.py.

...

class Command(BaseCommand):

    def handle(self, *args, **options):
        ...
        with open(user_file,'r') as f:
            ...

            for female_user in jdata['female']:
                ...


            for female_user in jdata['male']:
                female_user = UserProfile.objects.get(username=female_user['username'])
                token, created = Token.objects.get_or_create(user=female_user)
                headers = {'Authorization': 'Token %s' % token.key}

                for male_user in jdata['female']:
                    male_user = UserProfile.objects.get(username=male_user['username'])
                    rez = requests.get(API_URL+'chat/get_room/%s' % male_user.id, headers=headers)
                    room_out = json.loads(rez.text)
                    print('chat room %s was created' % room_out['id'])
                    data = {"room": room_out['id'], "token": room_out['token'], "message": "Hello from %s" % female_user.username}
                    rez = requests.post(API_URL+'chat/create_message/', json=data, headers=headers)
                    message_out = json.loads(rez.text)
                    print('Message: %s' % message_out['message'])

admin

Добавим список контактов в серилизатор API запроса инициализацииbackend/account/serializers/init.py.

class InitSerializer(serializers.Serializer):
    ...
    contacts = serializers.ListField()

И в отображение backend/account/views/init.py.

class InitView(APIView):
    ...
    def get(self, request, format=None):
        ...
        contacts = []
        for contact in user.get_contacts():
            contacts.append(ContactSerializer(contact).data) 
        data = {
            ...
            'contacts': contacts \
        }

admin

Frontend, Angular.

Создаем простенькую стору под контакты frontend/projects/core/src/store/states/contact.ts.

export class Contact {
    ids: number[];
}

export const defaultState = [];

Акшин frontend/projects/core/src/store/actions/contact.ts.

import { Action } from '@ngrx/store';
import { ContactState } from './../states/contact';

export enum ContactActionTypes {
  UpdateContacts = '[Contact] Update contacts'
}

export class UpdateContacts implements Action {
  readonly type = ContactActionTypes.UpdateContacts;
  constructor(public payload: ContactState) {}
}

export type UserActionsUnion =
UpdateContacts;

Редьюсер.

Задать вопрос, прокомментировать.