原文发表于Medium, 作者:Farel Ellely, 大江狗翻译整理。
先弄清楚逻辑,然后其他所有事情都是学术性的。
开发人员在其网站上出售特定服务时经常会遇到实施某种会员制的需求,我们将在数分钟内做到这一点。本文仅专注于在现有Django应用程序中构建或集成会员制(Membership)/订阅(Subscription)系统。我们还可以使用贝Paypal或Stripe API来完成付款,但这是另一篇文章的一部分。
首先,我们将启动一个名为membership的新应用。
./manage.py startapp membership
接下来,我们将进入models.py并开始添加将要使用的必要模型。大多数实现将在数据库级别完成,因此,正确定义表之间的关系对保证我们会员制订阅系统的关系至关重要。
我们将需要3种模型:一个Membership模型存有关会员类型(免费,付费,高级会员等等)及价格信息,一个UserMembership模型保存用户及其所选的会员类型,最后一个Subscription模型,可以用于存储会员订阅的时间以及是否active等信息。
让我们先从Memebership模型开始。
from django.db import models
from django.conf import settings
# Create your models here.
MEMBERSHIP_CHOICES = (
(‘Premium’, ‘pre’),
(‘Free’, ‘free’)
)
class Membership(models.Model):
slug = models.SlugField(null=True, blank=True)
membership_type = models.CharField(
choices=MEMBERSHIP_CHOICES, default=’Free’,
max_length=30
)
price = models.DecimalField(default=0)def __str__(self):
return self.membership_type
为了学习,我们仅创建了两个级别的会员类型,但这取决于您。slug属性将用于URL展示。接下来,我们继续创建UserMembership模型。
class UserMembership(models.Model):
user = models.OneToOneField(settings.AUTH_USER_MODEL, related_name=’user_membership’, on_delete=models.CASCADE)
membership = models.ForeignKey(Membership, related_name=’user_membership’, on_delete=models.SET_NULL, null=True)
def __str__(self):
return self.user.username
此类仅包含两个属性user和membership
user:与用户User模型是OneToOne的关系。
membership:它与Membership模型是单对多的关系,因为一种Membership可以包含很多成员。
最后,我们将添加Subscription模型。
class Subscription(models.Model):
user_membership = models.ForeignKey(UserMembership, related_name=’subscription’, on_delete=models.CASCADE)
active = models.BooleanField(default=True)
def __str__(self):
return self.user_membership.user.username
在这里,我们也有一个到UserMembership的外键,然后添加另一个属性来检查user_membership是否处于活动状态。
现在进行迁移,然后通过运行来应用它们。
./manage.py makemigrations membership
./manage.py migrate
正如我在开始时所说的,最具挑战性的方面是在数据库级别正确处理表与表之前的关系,这是我们到目前为止所做的,现在我们需要看到它的作用。
首先在 admin.py
### admin.py
from .models import Membership, UserMembership, Subscription
# Register your models here
admin.site.register(Membership)
admin.site.register(UserMembership)
admin.site.register(Subscription)
跳过管理界面,并添加两个成员资格实体:免费和高级。
我们接下来需要添加一个视图功能,该功能将负责显示所有可用的会员计划。
## views.py
from django.views.generic import ListView
from membership.models import Membership, UserMembership, Subscription
class MembershipView(ListView):
model = Membership
template_name = 'memberships/list.html'
def get_user_membership(self):
user_membership_qs = UserMembership.objects.filter(user=self.request.user)
if user_membership_qs.exists():
return user_membership_qs.first()
return None
def get_context_data(self, *args, **kwargs):
context = super().get_context_data(**kwargs)
current_membership = self.get_user_membership(self.request)
context['current_membership'] = str(current_membership.membership)
return context
然后,我们需要连接将调用视图函数的URL,并最终返回HTML模板。
### urls.py
from django.urls import path, include
from . import views
app_name = 'membership'
urlpatterns = [
path('memberships/', views.MembershipView.as_view(), name='select'),
]
HTML模板
{% block content %}<div class="container"><br><h1>Choose a plan according to your needs</h1><hr><div class="row">{% for object in object_list %}<div class="col-sm-4 col-md-4"><div class="card" style="width: 18rem;"><!-- <img class="card-img-top " src="{{ object.image.url }}" alt="Card image cap"> --><div class="card-body"> <h5 class="card-title"> {{ object.membership_type }}</h5> <p class="card-text"> {{ object.desc | linebreaks }} </p> </div> <ul class="list-group list-group-flush"> <li class="list-group-item"> ${{ object.price }}<small>/month</small></li> </ul> <div class="card-body"> {% if object.membership_type != 'Free' %} <form method="POST" action="{% url 'web:select' %}"> {% csrf_token %} {% if object.membership_type != current_membership %} <button class="btn btn-warning">Change</button> {% else %} <small>Your current plan</small> {% endif %} <input type="hidden" name="membership_type" value="{{ object.membership_type }}"> </form> {% endif %}</div> </div></div>{% endfor %}</div></div> {% endblock content %}
现在只能看到可用的内容,我们需要在用户注册时处理用户成员资格的创建。打开包含用于处理用户注册的代码的文件(我确实在SignUpForm中处理我的代码)。
### import datetimefrom django import forms
from django.forms import ModelForm
from django.contrib.auth.forms import UserCreationForm
from membership.models import Membership, UserMembership, Subscriptionclass SignUpForm(UserCreationForm):
free_membership = Membership.objects.get(membership_type=’Free’) class Meta(UserCreationForm.Meta):
model = User def save(self):
user = super().save(commit=False)
user.save() # Creating a new UserMembership
user_membership = UserMembership.objects.create(user=user, membership=self.free_membership)
user_membership.save() # Creating a new UserSubscription
user_subscription = Subscription()
user_subscription.user_membership = user_membership
user_subscription.save()
return user
我们正在做的就是简单地查询Free成员资格,然后将其分配给新注册的用户,最后返回该特定用户。这是每个会员系统背后的逻辑,希望您能够得到它,如果没有,请随时留言,我们将乐意遵循。
Cheers。
原文地址:
https://levelup.gitconnected.com/building-a-membership-system-in-django-under-5-mins-5efd7e03627d