<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Alex Kotov</title>
    <description>The latest articles on DEV Community by Alex Kotov (@mur4ik18).</description>
    <link>https://dev.to/mur4ik18</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F734519%2F3e9223eb-f798-4e6d-887b-ec6a5bd867ac.jpeg</url>
      <title>DEV Community: Alex Kotov</title>
      <link>https://dev.to/mur4ik18</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/mur4ik18"/>
    <language>en</language>
    <item>
      <title>I wrote django referral system</title>
      <dc:creator>Alex Kotov</dc:creator>
      <pubDate>Wed, 26 Jan 2022 12:20:05 +0000</pubDate>
      <link>https://dev.to/mur4ik18/i-wrote-django-referral-system-5c0l</link>
      <guid>https://dev.to/mur4ik18/i-wrote-django-referral-system-5c0l</guid>
      <description>&lt;p&gt;Hello, for work I needed to write a referral system on django!&lt;br&gt;
What the requirements:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;user can sign up only with exists referral code&lt;/li&gt;
&lt;li&gt;one referral code = one user&lt;/li&gt;
&lt;li&gt;when user sign up we give 3 referral code for his friends
What the technical requirements:&lt;/li&gt;
&lt;li&gt;django&lt;/li&gt;
&lt;li&gt;django rest framework&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Also I used:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;djoser&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;github repo:&lt;br&gt;
&lt;a href="https://github.com/mur4ik18/django-referral-system"&gt;https://github.com/mur4ik18/django-referral-system&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;First what I needed to write - create 2 app "referral_system" and "user".&lt;/p&gt;

&lt;p&gt;My referral_system models:&lt;br&gt;
models.py&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;from django.db import models
from django.conf import settings

class ReferralRelationship(models.Model):
    # who invite 
    employer = models.ForeignKey(
        settings.AUTH_USER_MODEL,
        related_name='inviter',
        verbose_name="inviter",
        on_delete=models.CASCADE,
    )
    # who connected 
    employee = models.ForeignKey(
        settings.AUTH_USER_MODEL,
        related_name='invited',
        verbose_name="invited",
        on_delete=models.CASCADE,
    )
    # referral code
    refer_token = models.ForeignKey(
        "ReferralCode",
        verbose_name="referral_code",
        on_delete=models.CASCADE,
    )
    def __str__(self) -&amp;gt; str:
        return f"{self.referrer}_{self.referred}"

class ReferralCode(models.Model):
    token = models.CharField(unique=True, max_length=150)
    user = models.ForeignKey(
        settings.AUTH_USER_MODEL, verbose_name="code_master", on_delete=models.CASCADE
    )
    def __str__(self) -&amp;gt; str:
        return f"{self.user}_{self.token}"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the project I override standard user django model, cause we need to add new field and required field- referral_token&lt;br&gt;
Also we need override standard UserManager cause we should add checking and writing tokens for new users and update referral relationships&lt;br&gt;
user/models.py&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;from django.db import models
from django.contrib.auth.models import AbstractUser
from .manager import UserManager

class User(AbstractUser):
    referral_token = models.CharField(max_length=255)
    # redefining standard user manager
    objects = UserManager()
    # add new required field "referral_token"
    REQUIRED_FIELDS = ["referral_token", "email"]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In 'manager.py' I added new required argument - referral_token&lt;/p&gt;

&lt;p&gt;user/manager.py&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;from referral_system.models import ReferralRelationship, ReferralCode
import secrets
from django.contrib.auth.models import BaseUserManager

class UserManager(BaseUserManager):
    def create_user(self, username, email, password=None, referral_token=None):
        # checking if user add all fields
        if not referral_token:
            raise ValueError("Please use your token!")
        if not email:
            raise ValueError("Users must have an email address!")
        # getting referral code and if code is not exist return error
        ref_code = ReferralCode.objects.filter(token=referral_token)
        if not ref_code:
            raise ValueError("Your token is not valid!")

        print(ref_code[0].user)

        # check code before using
        usages_token = ReferralRelationship.objects.filter(refer_token=ref_code[0])
        if not usages_token:
            # create user
            user = self.model(
                username=username, email=self.normalize_email(email), referral_token=referral_token
            )
            user.set_password(password)
            user.save(using=self._db)
            # create relationship for inviter and invited persone
            ReferralRelationship(
                employer=ref_code[0].user, employee=user, refer_token=ref_code[0]
            ).save()
            # create for new user 3 referall code (for frends)
            for i in range(3):
                self.create_reftoken(user)

        else:
            raise ValueError("This token is used!")

        return user

    def create_superuser(self, username, email, password=None, referral_token=None):
        # admin can use defunct referral code
        user = self.model(username=username, email=email, referral_token=referral_token)
        # set password and andmin things
        user.set_password(password)
        user.is_admin = True
        user.is_superuser = True
        user.is_staff = True
        user.save(using=self._db)
        # create 5 referral codes
        for i in range(5):
            self.create_reftoken(user)
        return user

    # method for creating tokens
    def create_reftoken(self, user):
        token = secrets.token_urlsafe(20)
        ReferralCode(token=token, user=user).save()
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;*&lt;em&gt;If you know better how to write this piece of code, I would be grateful if you could tell me *&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;for i in range(5):
    self.create_reftoken(user)

def create_reftoken(self, user):
    token = secrets.token_urlsafe(20)
    ReferralCode(token=token, user=user).save()
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Then&lt;/strong&gt;&lt;br&gt;
I created simple m2o (many to one) serializer&lt;/p&gt;

&lt;p&gt;referral_system/serializers.py&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import secrets
from rest_framework import serializers
from .models import ReferralCode, ReferralRelationship

class ReferralSerializer(serializers.ModelSerializer):
    class Meta:
        model = ReferralRelationship
        fields = [
            "employer",
            "employee", 
            "refer_token"]

class RefferCodeSerializer(serializers.ModelSerializer):
    refer_relations = ReferralSerializer(many=True, default="")
    class Meta:
        model = ReferralCode
        fields = [
            "token", 
            "user", 
            "refer_relations"]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and views.py&lt;br&gt;
referral/views.py&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;from rest_framework import status
from rest_framework.response import Response
from rest_framework.generics import ListAPIView
from .models import ReferralCode
from .serializers import RefferCodeSerializer

class RefferCodeJsonListView(ListAPIView):
    def get(self, request):
        # getting querry set with referral codes for user who make request
        queryset = ReferralCode.objects.filter(user=request.user)
        data = RefferCodeSerializer(queryset, many=True)
        return Response(data.data, status=status.HTTP_200_OK)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;How my system works&lt;/strong&gt;&lt;br&gt;
Admin signup - my system create 5 referral codes. Then admin send 5 codes for first users. Every new user get 3 referral codes for friends. The number of users will grow exponentially (boom grow)&lt;/p&gt;

&lt;p&gt;I am open to criticism and if you wanna contrib this project you are welcome:&lt;br&gt;
&lt;a href="https://github.com/mur4ik18/django-referral-system"&gt;https://github.com/mur4ik18/django-referral-system&lt;/a&gt;&lt;/p&gt;

</description>
      <category>django</category>
      <category>python</category>
      <category>programming</category>
      <category>tutorial</category>
    </item>
  </channel>
</rss>
