Django Businesses Logic 

Ivaylo Bachvarov 

ivaylo@hacksoft.io

class RealEstate(models.Model):
    seller = models.ForeignKey(User)


class Negotiation(models.Model):
    real_estate=models.ForeignKey(RealEstate, related_name='negotiations')
    buyer = models.ForeignKey(User)


class Offer(models.Model):
    PENDING = 0
    REJECTED = 1
    ACCEPTED = 2
    WITHDRAWN = 3

    STATUS_CHOICES = (
        (PENDING, 'Pending'),
        (REJECTED, 'Rejected'),
        (WITHDRAWN, 'Withdrawn'),
        (ACCEPTED, 'Accepted'),
    )

    status = models.IntegerField(choices=STATUS_CHOICES, default=NEW)
    negotiation = models.ForeignKey(Negotiation, related_name='offers')
    offer_amount = models.PositiveIntegerField()
    is_buyer_origin = models.BooleanField()

Lets create some APIs

@api_view(['GET', 'POST'])
def offers_api(request):
    if request.method == 'GET':
        offers = Offer.objects.all()
        serializer = OfferSerializer(snippets, many=True)
        return Response(serializer.data)

    elif request.method == 'POST':
        serializer = OfferSerializer(data=request.data)
        if serializer.is_valid():
            serializer.save()
            return Response(serializer.data, status=status.HTTP_201_CREATED)
        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
class OffersListAPI(generics.ListCreateAPIView):
    queryset = Offers.objects.all()
    serializer_class = OffersSerializer


class NegotiationsListAPI(generics.ListCreateAPIView):
    queryset = Negotiation.objects.all()
    serializer_class = NegotiationSerializer
class NegotiationsListAPI(generics.ListCreateAPIView):
    queryset = Negotiation.objects.all()
    serializer_class = NegotiationSerializer

    def perform_create(self, serializer):
        serializer.save(owner=self.request.user)
class NegotiationsListAPI(generics.ListCreateAPIView):
    queryset = Negotiation.objects.all()
    serializer_class = NegotiationSerializer

    def perform_create(self, serializer):
        negotiation = serializer.save(owner=self.request.user)
        # Send an email
        context = {
            "creator_name": self.request.full_name,
            "property_address": negotiation.real_estate.address
        }
        send_email.delay(email=self.request.email, context=context)
class OffersListAPI(generics.ListCreateAPIView):
    queryset = Offers.objects.all()
    serializer_class = OfferSerializer

    def perform_create(self, serializer):
        offer = serializer.save()
        options = {
            'page-size': 'Letter',
            'margin-top': '0.75in',
            'margin-right': '0.75in',
            'margin-bottom': '0.75in',
            'margin-left': '0.75in',
            'encoding': "UTF-8",
        }

        pdfkit.from_file('offer.html', 'offer.pdf',
                         options=options, context=offer)
class OffersListAPI(generics.ListCreateAPIView):
    queryset = Offers.objects.all()
    serializer_class = OfferSerializer

    def perform_create(self, serializer):
        negotiation = validated_data['negotiation']
        if negotiation.latest_offer.status in [Offer.PENDING, Offer.NEW]:
            raise ValidationError("You can`t create new offer.\
                    There is an offer that is currently pending.")

        offer = serializer.save()
        options = {
            'page-size': 'Letter',
            'margin-top': '0.75in',
            'margin-right': '0.75in',
            'margin-bottom': '0.75in',
            'margin-left': '0.75in',
            'encoding': "UTF-8",
        }

        pdfkit.from_file('offer.html', 'offer.pdf',
                         options=options, context=offer)

Signals

# views.py
class OffersListAPI(generics.ListCreateAPIView):
    queryset = Offers.objects.all()
    serializer_class = OfferSerializer

    def perform_create(self, serializer):
        negotiation = validated_data['negotiation']
        if negotiation.latest_offer.status in [Offer.PENDING, Offer.NEW]:
            raise ValidationError("You can`t create new offer.\
                    There is an offer that is currently pending.")
        serializer.save()

# signals.py
@receiver(post_save, sender=Offer)
def generate_offer_pdf(sender, instance, created, **kwargs):
    if created:
        options = {
            'page-size': 'Letter',
            'margin-top': '0.75in',
            'margin-right': '0.75in',
            'margin-bottom': '0.75in',
            'margin-left': '0.75in',
            'encoding': "UTF-8",
        }

        pdfkit.from_file('offer.html', 'offer.pdf',
                         options=options, context=offer)

Clean

# views.py
class OffersListAPI(generics.ListCreateAPIView):
    queryset = Offers.objects.all()
    serializer_class = OfferSerializer

    def perform_create(self, serializer):
        negotiation = validated_data['negotiation']
        if negotiation.latest_offer.status in [Offer.PENDING, Offer.NEW]:
            raise ValidationError("You can`t create new offer.\
                    There is an offer that is currently pending.")
        serializer.save()

# signals.py
@receiver(post_save, sender=Offer)
def generate_offer_pdf(sender, instance, created, **kwargs):
    if created:
        options = {
            'page-size': 'Letter',
            'margin-top': '0.75in',
            'margin-right': '0.75in',
            'margin-bottom': '0.75in',
            'margin-left': '0.75in',
            'encoding': "UTF-8",
        }

        pdfkit.from_file('offer.html', 'offer.pdf',
                         options=options, context=offer)

Models

# models.py
class Offer(models.Model):
    def clean(self):
        if self.negotiation.latest_offer.status in [Offer.PENDING, Offer.NEW]:
            raise ValueError("You can`t create new offer.\
                    There is an offer that is currently pending.")
        
# views.py
class OffersListAPI(generics.ListCreateAPIView):
    queryset = Offers.objects.all()
    serializer_class = OfferSerializer


# signals.py
@receiver(post_save, sender=Offer)
def generate_offer_pdf(sender, instance, created, **kwargs):
    if created:
        options = {
            'page-size': 'Letter',
            'margin-top': '0.75in',
            'margin-right': '0.75in',
            'margin-bottom': '0.75in',
            'margin-left': '0.75in',
            'encoding': "UTF-8",
        }

        pdfkit.from_file('offer.html', 'offer.pdf',
                         options=options, context=offer)
# models.py
class Offer(models.Model):
    def clean(self):
        if self.negotiation.latest_offer.status in [Offer.PENDING, Offer.NEW]:
            raise ValueError("You can`t create new offer.\
                    There is an offer that is currently pending.")
        
# views.py
class OffersListAPI(generics.ListCreateAPIView):
    queryset = Offers.objects.all()
    serializer_class = OfferSerializer

    @detail_route(methods=['post'])
    def accept(self, request, pk=None):
        offer = self.get_object()
        serializer = AcceptfSerializer(data=request.data)
        if serializer.is_valid():
            offer.status = Offer.ACCPETED
            offer.accepted_on = timezone.now()
            user.save()
            return Response(OfferSerializer(offer).data,
                            status=status.HTTP_200_OK)
        else:
            return Response(serializer.errors,
                            status=status.HTTP_400_BAD_REQUEST)    

# signals.py
@receiver(post_save, sender=Offer)
def generate_offer_pdf(sender, instance, created, **kwargs):
    if created:
        options = {
            'page-size': 'Letter',
            'margin-top': '0.75in',
            'margin-right': '0.75in',
            'margin-bottom': '0.75in',
            'margin-left': '0.75in',
            'encoding': "UTF-8",
        }

        pdfkit.from_file('offer.html', 'offer.pdf',
                         options=options, context=offer)
# permissions.py
class OnlySellerCanCreate(permissions.BasePermission):

    def has_permission(self, request, view):
        if not request.method == 'POST':
            negotiation_id = request.data['negotiation']
            real_estate = RealEstate.objects.get(negotiation=real_estate_id)
            return self.request.user in real_estate.sellers

# models.py
class Offer(models.Model):
    def clean(self):
        if self.negotiation.latest_offer.status in [Offer.PENDING, Offer.NEW]:
            raise ValueError("You can`t create new offer.\
                    There is an offer that is currently pending.")
        
# views.py
class OffersListAPI(generics.ListCreateAPIView):
    queryset = Offers.objects.all()
    serializer_class = OfferSerializer

    @detail_route(methods=['post'])
    def accept(self, request, pk=None):
        offer = self.get_object()
        ......... 

# signals.py
@receiver(post_save, sender=Offer)
def generate_offer_pdf(sender, instance, created, **kwargs):
    if created:
        options = {
            'page-size': 'Letter',
            'margin-top': '0.75in',
            'margin-right': '0.75in',
            'margin-bottom': '0.75in',
            'margin-left': '0.75in',
            'encoding': "UTF-8",
        }

        pdfkit.from_file('offer.html', 'offer.pdf',
                         options=options, context=offer)

Services

def create_offer(offers_amount, negotiation, user):
    real_estate = RealEstate.objects.get(negotiation=negotiation)
    if self.request.user not in real_estate.sellers:
        raise PermissionDenied("You can create offer for this estate!")

    if negotiation.latest_offer.status in [Offer.PENDING, Offer.NEW]:
            raise ValueError("You can`t create new offer.\
                    There is an offer that is currently pending.")

    offer = Offer.objects.create(offer_amount=offer_amount, negotiation=negotiation)
    options = {
        'page-size': 'Letter',
        'margin-top': '0.75in',
        'margin-right': '0.75in',
        'margin-bottom': '0.75in',
        'margin-left': '0.75in',
        'encoding': "UTF-8",
    }

    pdfkit.from_file('offer.html', 'offer.pdf', options=options, context=offer)

    return offer

Services calling

# views.py
class OffersListAPI(generics.ListCreateAPIView):
    queryset = Offers.objects.all()
    serializer_class = OfferSerializer

    def create(self, request, *args, **kwargs):
        serializer = self.get_serializer(data=request.data)
        serializer.is_valid(raise_exception=True)
        obj = create_offer(**serializer.validated_data, user=self.request.user)
        serializer = self.get_serializer(obj)
        headers = self.get_success_headers(serializer.data)
        return Response(serializer.data, status=status.HTTP_201_CREATED, headers=headers)

Services++

def create_offer(*, offers_amount, negotiation, user):
    real_estate = RealEstate.objects.get(negotiation=negotiation)
    if self.request.user not in real_estate.sellers:
        raise PermissionDenied("You can create offer for this estate!")

    if negotiation.latest_offer.status in [Offer.PENDING, Offer.NEW]:
            raise ValueError("You can`t create new offer.\
                    There is an offer that is currently pending.")

    offer = Offer.objects.create(offer_amount=offer_amount, negotiation=negotiation)
    options = {
        'page-size': 'Letter',
        'margin-top': '0.75in',
        'margin-right': '0.75in',
        'margin-bottom': '0.75in',
        'margin-left': '0.75in',
        'encoding': "UTF-8",
    }

    pdfkit.from_file('offer.html', 'offer.pdf', options=options, context=offer)

    return offer

Services+++

def _check_if_user_is_seller(negotiation, user):
    real_estate = RealEstate.objects.get(negotiation=negotiation)
    if self.request.user not in real_estate.sellers:
        raise PermissionDenied("You can create offer for this estate!")

def _check_for_other_pending_offers(negotiation):
    if negotiation.latest_offer.status in [Offer.PENDING, Offer.NEW]:
        raise ValueError("You can`t create new offer.\
                    There is an offer that is currently pending.")

def _genarete_offer_pdf(offer):
   options = {
        'page-size': 'Letter',
        'margin-top': '0.75in',
        'margin-right': '0.75in',
        'margin-bottom': '0.75in',
        'margin-left': '0.75in',
        'encoding': "UTF-8",
    }

    pdfkit.from_file('offer.html', 'offer.pdf', options=options, context=offer)

def create_offer(*, offers_amount, negotiation, user):
    _check_if_user_is_seller(negotiation, user)
    _check_for_other_pending_offers(negotiation)

    offer = Offer.objects.create(offer_amount=offer_amount, negotiation=negotiation)

    _generate_offer_pdf(offer)
    return offer

Services+++

.......

def create_offer(*,
                 offers_amount: int,
                 negotiation: Negotiation,
                 user: User) -> Offer:
    _check_if_user_is_seller(negotiation, user)
    _check_for_other_pending_offers(negotiation)

    offer = Offer.objects.create(offer_amount=offer_amount, negotiation=negotiation)

    _generate_offer_pdf(offer)
    return offer

Services+++

class ServiceExceptionHandlerMixin:
    expected_exceptions = {
        ValidationError: serializers.ValidationError,
        ValueError: serializers.ValidationError,
    }

    def handle_exception(self, exc):
        if isinstance(exc, tuple(self.expected_exceptions.keys())):
            drf_exception_class = self.expected_exceptions[exc.__class__]
            drf_exception = drf_exception_class(get_error_message(exc))

            return super().handle_exception(drf_exception)

        return super().handle_exception(exc)

Django Business Logic - Django Meetup

By Hack Bulgaria

Django Business Logic - Django Meetup

Уводната лекция за курса по Програмиране 0

  • 1,581