Niffler

X2.03 16340286-My Django Models

Posted By 16340286

The source code is in questionnaire/models.py.

Logic Design

  • When create task, available_balance should be more than fee * participant_quota.

  • When determine task’s fee, participant_quota should also be determined but not vice versa.

  • Task’s due_date is only w.r.t. participantship’s participanted_date, so participantship’s confirmed_date is unrestricted.

  • When create a participantship, task issuer’s balance is deducted 1 * fee.

  • When task cancelled, task issuer will not be refunded and affect corresponding participantship, participant whose _status == ‘UNDERWAY’ will be paid.

  • Task can be claimed when status == ‘UNDERWAY’ and claimer is not issuer.

  • When task invalid, task issuer will not be refunded and cause corresponding participantship invalid, participant whose _status == ‘UNDERWAY’ will NOT be paid.

  • Only participant has permission to modify _status from ‘UNDERWAY’ to ‘CANCELLED’ and task issuer is refunded 1 * fee.

  • Only task issuer has permission to modify _status from ‘UNDERWAY’ to ‘CONFIRMED’ and participant is paid 1 * fee.

  • Only task issuer has permission to comment when _status == ‘CONFIRMED’.

Status Design

Task statuses:
        INVALID : Has certain number of claimers
      CANCELLED : Cancelled by issuer
         CLOSED : due_date expires
     QUOTA FULL : Attain to participant_quota
       UNDERWAY : In progress

Participantship statuses:
      CANCELLED : Cancelled by participant
      COMMENTED : Has been commented by its task issuer
      CONFIRMED : Has been confirmed by its task issuer
   TASK INVALID : Its task has certain number of claimers
 TASK CANCELLED : Its task has been cancelled
       UNDERWAY : In progress

Play with The Models

You can first hop into the interactive Python shell and play around with using this command

$ python3 manage.py shell

It will set the DJANGO_SETTINGS_MODULE environment variable.

The following code shows how to manipulate the Django models I design. I will also specify some of them.

# Create User
from questionnaire.models import Profile, Task, Tag, Participantship
from django.contrib.auth.models import User
user4 = User.objects.create_user(
    username='user4', email='user4@niffler.com', password='user4')
user4 = User.objects.get(pk=4) # same
Profile.objects.create(user=user4, phone='16666666664')
>>> <Profile: Profile object (4)>

# Reverse Retrieve
user4.profile.phone
>>> '16666666664'
user4.profile.balance
>>> 10000

# Create Task
"""
TODO:
    - ensure issuer's balance >= (fee * participant_quota of all his active task)
    - ensure participant_quota should be not null when fee is not null 
    - if someone participant the task, the issuer's balance will deduct 1 * fee
    - if issuer cancel the task, actual participants' amount * fee will not be refunded
    - the status property will indicate whether it is expired
    - the task becomes invalid when claimers' amount exceeds the threshold, actual participants' amount * fee will not be refunded
"""
user1 = User.objects.get(pk=1) # query by pk
task1 = Task(title='What is 1+1?', issuer=user1)
task1.save() # another way to create
user1.issued_tasks.all() # call by related_name
>>> <QuerySet [<Task: Task object (1)>]>

# Convert Time Zone
from pytz import timezone
cst_tz = timezone('Asia/Shanghai')
task1.created_date.astimezone(cst_tz)
>>> datetime.datetime(2019, 6, 2, 16, 6, 41, 797096, tzinfo=<DstTzInfo 'Asia/
Shanghai' CST+8:00:00 STD>)

# Update
task1 = Task.objects.get(pk=1)
task1.title='Why is is 1+1?'
task1.save()
Task.objects.get(pk=1).title
>>> 'Why is is 1+1?'

# Modify auth.User
user3 = User.objects.get(pk=3)
user3.username = 'user3'
user3.email = 'user3@niffler.com'
user3.set_password('user3')
user3.save()

# Verify Password
from django.contrib.auth import authenticate
not not authenticate(username='user3', password='user4')
>>> False
not not authenticate(username='user3', password='user3')
>>> True

# Create Tag
Tag(name='Math').save()
tag1 = Tag.objects.get(name='Math') # query by name
tag1.tasks.add(task1) # error if tag1 is not saved
task1.tag_set.all()
>>> <QuerySet [<Tag: Tag object (1)>]>
tag1.tasks.all()
>>> <QuerySet [<Task: Task object (1)>]>

# Participate Task
"""
TODO:
    - issuer should not be participant
    - if participant cancel the task, refund issuer 1 * fee
    - for simplicity, if issuer confirm the task, participant can obtain 1 * fee, issuer can rate and comment
    - for simplicity, the task finished_date is unrelated to due_date
    - if the task becomes invalid, participant cannot obtain 1 * fee
""" 
Participantship(user=user2, task=task1).save()
user2.participanted_tasks.all()
>>> <QuerySet [<Task: Task object (1)>]>
user2.participantship_set.all()
>>> <QuerySet [<Participantship: Participantship object (1)>]>
task1.participantship_set.all()
>>> <QuerySet [<Participantship: Participantship object (1)>]>
user2.participantship_set.all()[0].participanted_date
>>> datetime.datetime(2019, 6, 2, 9, 16, 1, 489484, tzinfo=<UTC>)