These docs are a work-in-progress and are currently undergoing a major rewrite!

Quickstart models

The quickstart comes with two sets of models that are useful for most projects.

The first is a custom users app with a User model. If you need to store custom data related to a user, you can put fields directly on this model. A custom user model is the recommended way to start a project according to the Django docs.

The second is a teams app, that includes the Team and TeamMembership models. Most projects inevitably need some type of "Team" concept, so it's one of the few places we like to provide a starting point. You can call it something else in your frontend HTML (ex. "Organization" or "Group"), but in general the Team is where you'll group users together and attach billing information.

You don't have to use the teams app if you know you aren't going to need it or prefer a different naming convention. We would strongly recommend you keep a custom users app/model though.

Users

We include two modifications to what the Django AbstractUser provides:

  • the email for a user must be unique (helps with login and duplication)
  • the uuid field is added via UUIDModel (helps with identifying users without exposing the standard auto-incrementing ID)

When you need to store something directly on a user, go ahead and write your code in the User model:

class User(AbstractUser, UUIDModel):
    email = models.EmailField(unique=True)

    # Add your own fields and methods here!

SignupView

The quickstart comes with all of the django.contrib.auth.urls enabled at the root (ex. "example.com/login/"). This includes:

  • login
  • logout
  • password changes
  • password resets

We also include a standard signup form to let users create an account using username, email address, and password.

urlpatterns = [
    # ...
    path("signup/", SignupView.as_view(), name="signup"),
    path("", include("django.contrib.auth.urls")),
]

Django signup form

When someone completes the signup form, they'll be redirected to log in using their new account. You can customize the SignupView to log them in immediately, show welcome messages, or start an email confirmation flow first.

Teams

When you're setting up the relationships in your project, most of the time you'll want to associate things with a "team" rather than a "user".

Whether you need teams right off the bat or plan to support them later, it's a good idea to tie "projects", billing, etc. to a Team even if that team is just a single User. Down the road, if you need to transfer a "project" from a user to their company team, you can effectively do a Team->Team transfer which is much simpler than changing the type of relationship from a User to a Team.

Likewise, if you plan to support subscriptions for individuals and businesses, you should consider both of those to be a Team on the backend which will simplify a lot of the billing logic.

Teams in Forge come with a few fields we think are useful, but you can customize is from there:

class Team(TimestampModel, UUIDModel):
    name = models.CharField(max_length=255)
    members = models.ManyToManyField(
        "users.User",
        related_name="teams",
        through="TeamMembership"
    )

    # Add your own fields and methods here!


class TeamRoles(models.TextChoices):
    ...


class TeamMembership(TimestampModel, UUIDModel):
    ...

Roles

When you add people to teams, we also provide a role field with basic ADMIN or MEMBER options. You can add to these as needed, but if you aren't using roles right away then just make everyone a MEMBER so you can add admin-specific features later!

team = Team.objects.create("A new team")
team_member1 = TeamMembership.objects.create(
    team=team,
    user=user,
    role=TeamRoles.MEMBER,
)