Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • SEARCH
  • Home
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 7609829
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: May 31, 20262026-05-31T01:16:09+00:00 2026-05-31T01:16:09+00:00

I am trying to create a task list with each task having a datetime

  • 0

I am trying to create a task list with each task having a datetime attribute. The tasks needs to be in order with t_created being the first and t_paid being last. The order is shown in step_datetime. The description for each tasks is in STEPS.

I currently have two methods all_steps and next_step that shows the task list information. The two methods also need to display the name of the user_created, but that variable won’t be defined until the methods are called. That’s why I am doing a string replace method.

I feel like I am repeating my code a lot, and I want to follow the DRY principle of Django. Is there any way I could improve this code?

Here is my full code:

class Order( models.Model ) :
    def __unicode__( self ) :
        return unicode( self.id )

    def comments_count( self ) :
        return OrderComment.objects.filter( order = self.id ).count()

    def all_steps( self ) :
        user = self.user_created.first_name

        steps = []
        step_datetime = [
            self.t_created,
            self.t_action,
            self.t_followup_one,
            self.t_vendor_appt_one,
            self.t_vendor_appt_two,
            self.t_work_done,
            self.t_followup_two,
            self.t_paid,
        ]

        for ( i, step ) in enumerate( self.STEPS ) :
            steps.append( ( step_datetime[ i ], step.replace( '<user_created>', user ), ) )

        return steps

    def next_step( self ) :
        user = self.user_created.first_name

        step = 0
        if self.t_action is None :
            step = 0
        elif self.t_followup_one is None :
            step = 1
        elif self.t_vendor_appt_one is None :
            step = 2
        elif self.t_vendor_appt_two is None :
            step = 3
        elif self.t_work_done is None :
            step = 4
        elif self.t_followup_two is None :
            step = 5
        elif self.paid is None :
            step = 6

        return str( step ) + ": " + self.STEPS[ step ].replace( '<user_created>', user )


    STEPS = [
        "Review, then either approve or reject the order.",
        "Follow up with <user_created>",
        "Contact the vendor to get a quote and arrange an appointment for <user_created>.",
        "Review the quote, (get owner approval), then arrange a second appointment for the repairs.",
        "Confirm the finished repairs and pay the vendor.",
        "Follow up again with <user_created>",
        "Confirm payment and close the order.",
    ]

    ACTION_CHOICES = (
        ( 'p', 'pending'  ),
        ( 'a', 'approved' ),
        ( 'r', 'rejected' ),
        ( 'c', 'closed'   ),
    )

    user_created      = models.ForeignKey( User, related_name = 'user_created', verbose_name = 'created by' )
    user_action       = models.ForeignKey( User, related_name = 'user_status' , verbose_name = 'action by' , null = True, blank = True )
    t_created         = models.DateTimeField( auto_now_add = True, verbose_name = 'created' )
    t_action          = models.DateTimeField( null = True, blank = True, verbose_name = 'action'             )
    t_followup_one    = models.DateTimeField( null = True, blank = True, verbose_name = 'first follow-up'    )
    t_vendor_appt_one = models.DateTimeField( null = True, blank = True, verbose_name = 'first appointment'  )
    t_vendor_appt_two = models.DateTimeField( null = True, blank = True, verbose_name = 'second appointment' )
    t_work_done       = models.DateTimeField( null = True, blank = True, verbose_name = 'work done'          )
    t_followup_two    = models.DateTimeField( null = True, blank = True, verbose_name = 'second follow-up'   )
    t_paid            = models.DateTimeField( null = True, blank = True, verbose_name = 'paid'               )
    action            = models.CharField( max_length = 1, choices = ACTION_CHOICES, default = 'p' )
    quote             = models.DecimalField( max_digits = 8, decimal_places = 2, null = True, blank = True )
    payment           = models.DecimalField( max_digits = 8, decimal_places = 2, null = True, blank = True )
    items             = models.ManyToManyField( Item, null = True, blank = True )
    t_modified        = models.DateTimeField( auto_now = True, verbose_name = 'modified' )

After accepting @Dougal’s answer. I changed some of the variables around and came up with this:

def all_steps( self ) :
    user = self.user_created.first_name

    return [
        ( getattr( self, attr ), task.format( user = user ) )
        for ( attr, task ) in self.TASKS
    ]

def next_step( self ) :
    user = self.user_created.first_name

    task_num = next(
        ( i for ( i, ( attr, task ) ) in enumerate( self.TASKS ) if getattr( self, attr ) is None ),
        None
    )

    if task_num == None :
        return "Done!"
    else:
        return "{number}: {task}".format(
            number = str( task_num + 1 ),
            task   = self.TASKS[ task_num ][ 1 ].format( user = user )
        )

TASKS = (
    ( "t_action"         , "Review, then either approve or reject the order." ),
    ( "t_followup_one"   , "Follow up with {user}." ),
    ( "t_vendor_appt_one", "Contact the vendor to get a quote and arrange an appointment for {user}." ),
    ( "t_vendor_appt_two", "Review the quote, (get owner approval), then arrange a second appointment for the repairs." ),
    ( "t_work_done"      , "Confirm the finished repairs and pay the vendor." ),
    ( "t_followup_two"   , "Follow up again with {user}." ),
    ( "t_paid"           , "Confirm payment and close the order." ),
)
  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-05-31T01:16:10+00:00Added an answer on May 31, 2026 at 1:16 am

    Adding on to @Marcin’s answer:

    You could make a tuple of the property names (say _STEP_NAMES at the module level; you could also make it at the class level, like STEPS, or even just combine the two into a tuple of pairs of attributes and names; that might be a little cleaner). Also, STEPS should probably be a tuple, since it shouldn’t be modifiable at runtime.

    Then you can reduce your code to:

    def all_steps(self):
        user = self.user_created.first_name
        return [(getattr(self, attr), step.replace('<user_created>', user))
                for attr, step in zip(_STEP_NAMES, self.STEPS)]
    
    def next_step(self):
        user = self.user_created.first_name
        step = next((i for i, attr in enumerate(_STEP_NAMES)
                            if getattr(self, attr) is None),
                    None) # assumes Python 2.6+
        if step == None:
             return "Done!"
        else:
             return str(step) + ": " + self.STEPS[step].replace('<user_created>', user)
    

    If you need Python 2.4/2.5 compatability, the next line can be replaced by

    try:
        step = (i for i, attr in enumerate(_STEP_NAMES) if getattr(self, attr) is None).next()
    except StopIteration:
        return "Done!"
    return str(step) + ": " + self.STEPS[step].replace('<user_created>', user)
    
    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

I'm trying to create a dummy application that maintains a list of tasks. For
I am trying to create an API for chaining tasks. First, I designed a
I'm trying to create a to do list in android, where each item is
I am trying to create a unique taskID list based on the selections. Each
The task: I am trying to create a custom data type and have it
I am trying to figure out how to accomplish the following task: Create a
I'm trying to create an object called List. This object has a method add
I am trying to create a Task application with Backbone.Js. Task is a model
I am trying to create a model instance that includes a list of model
What I am trying to do is create ideally a nested List basically a

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.