【问题标题】:Django Model Terms of Service With Timestamp, Username, and Prompt User To Agree To Updated Terms of Service带有时间戳、用户名和提示用户同意更新的服务条款的 Django 模型服务条款
【发布时间】:2020-05-01 20:07:07
【问题描述】:

我想创建一个模型,其中包含时间戳和同意服务条款的当前登录用户的 allauth。然后,在每个页面上(如果用户已登录),注释用户是否同意最新的服务条款(通过将他们上次同意的时间戳与最新更新的服务条款的时间戳进行比较),如果用户尚未同意最新版本的服务条款,他们将被重定向到要求他们同意更新版本的页面。然后它将用户重定向回他们同意后的来源。

如何去创造这样的东西?

到目前为止我所拥有的如下。

模型.py:

from django.contrib.auth.models import User
class TermsOfService(models.Model):
    agreement = models.BooleanField(default=False)
    created_at = models.DateTimeField(auto_now_add=True,blank=True, null=True)
    user = models.ForeignKey(User, blank=True, null=True, on_delete=models.CASCADE)

    def __str__(self):
        return self.agreement

class UserMembership(models.Model):
    user = models.OneToOneField(
        settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
    stripe_customer_id = models.CharField(max_length=40, unique=True)
    membership = models.ForeignKey(
        Membership, on_delete=models.SET_NULL, null=True)

    def __str__(self):
        return self.user.username

Forms.py:

from .models import TermsOfService
class TermsOfServiceForm(forms.ModelForm):
    class Meta:
        model = TermsOfService
        fields = ('agreement',)

    def __init__(self, *args, **kwargs):
        super(TermsOfServiceForm, self).__init__(*args, **kwargs)
        self.fields['agreement'].widget.attrs={ 'id': 'agreement_field', 'class': 'form-control', 'required': 'true', 'autocomplete':'off'}

App Urls.py:

from django.urls import path
from .views import ( terms_of_service_view )
app_name = 'app'
urlpatterns = [ path('terms_of_service_view/', terms_of_service_view, name='terms_of_service_view'), ]

Views.py:

def get_user_membership(request):
    user_membership_qs = UserMembership.objects.filter(user=request.user)
    if user_membership_qs.exists():
        return user_membership_qs.first()
    return None

def terms_of_service_view(request):
    if request.method == 'POST':
        form = TermsOfServiceForm(request.POST)
        if form.is_valid():
            user_membership = get_user_membership(request)
            instance = form.save(commit=False)
            instance.user = request.user
            instance.save()

            context = {
            'user_membership': user_membership,
            'form':form
            }
            return render(request, "index.html", context)
    else: 
        form = TermsOfServiceForm()

    context = {
            'user_membership': user_membership,
            'form': form,
            }
    return render(request, "index.html", context)

【问题讨论】:

    标签: django django-models django-forms django-views django-allauth


    【解决方案1】:

    您的代码中出现了一个问题,例如您将如何确定用户何时需要同意协议,您是否在TermsOfService 中创建了一堆新条目。与其这样,不如创建一个名为 Terms 的新模型并将其添加为 ForeignKey。

    class Term(models.Model):
       text = models.TextField()
       created_at = models.DateTimeField(auto_now_add=True,blank=True, null=True)
       # blah blah
    
    class TermsOfService(models.Model):
        term = models.ForeignKey(Term, on_delete=models.DO_NOTHING)
        agreement = models.BooleanField(default=False)
        created_at = models.DateTimeField(auto_now_add=True,blank=True, null=True)
        user = models.ForeignKey(User, blank=True, null=True, on_delete=models.CASCADE)
    

    采用这种方式有一个好处,就是你需要做的就是新建一个Term对象,剩下的可以由中间件来处理。例如:

    from django.urls import reverse
    from django.shortcuts import redirect
    
    class TermAgreeMiddleware:
        def __init__(self, get_response):
            self.get_response = get_response
    
        def __call__(self, request):
            response = self.get_response(request)
            if not request.user.is_authenticated:
                return response
            term_date = Term.objects.last().created_at
            user_term_date = request.user.termofservice_set.filter(created_at__gte=term_date).exists()
            if not user_term_date:
                 return redirect(reverse('app:terms_of_service_view')+'?next='+request.path)     
            return response
    

    并更新视图:

    def terms_of_service_view(request):
        if request.method == 'POST':
            form = TermsOfServiceForm(request.POST)
            if form.is_valid():
                user_membership = request.user.usermembership  # you don't need another view as User has OneToOne relation with UserMembership
                instance = form.save(commit=False)
                instance.user = request.user
                instance.term = Term.objects.last()
                instance.save()
                go_next = request.GET.get('next', None)  # handle redirection
                if go_next:
                    return redirect(go_next)
                context = {
                'user_membership': user_membership,
                'form':form
                }
                return render(request, "index.html", context)
        else: 
            form = TermsOfServiceForm()
    
        context = {
                'user_membership': user_membership,
                'form': form,
                }
        return render(request, "index.html", context)

    最后在MIDDLEWARE 设置中添加TermAgreeMiddleware。因此,每当您希望用户同意一个新术语时,只需创建一个新的 Term 实例(来自管理站点或 shell)。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2022-01-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多