Django Типовые условия обслуживания с отметкой времени, именем пользователя и приглашением пользователя принять обновленные условия обслуживания - PullRequest
2 голосов
/ 15 января 2020

Я хотел бы создать модель, которая содержит временную метку и имя пользователя, который в настоящее время вошел в систему и согласился с Условиями обслуживания. Затем на каждой странице (если пользователь вошел в систему) аннотируйте, если пользователь согласился с последними Условиями обслуживания (сравнивая временную метку своего последнего соглашения с временной меткой последних обновленных Условий предоставления услуг), и если Пользователь не согласен с самой последней версией Условий обслуживания, которую он перенаправляет на страницу, требующую от него согласия на обновленную версию. Затем он перенаправляет пользователя назад, откуда они пришли после того, как они согласны.

Как можно go создать что-то подобное?

Ниже показано, что у меня есть.

Models.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'}

Приложение 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)

1 Ответ

0 голосов
/ 15 января 2020

В вашем коде возникает вопрос, например, как вы собираетесь определить, когда пользователь должен согласиться с соглашением, создаете ли вы новую запись в TermsOfService. Вместо этого, почему бы не создать новую модель с именем Термины и добавить ее как 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 = <b>request.user.usermembership  # you don't need another view as User has OneToOne relation with UserMembership</b>
            instance = form.save(commit=False)
            instance.user = request.user
            instance.term = Term.objects.last()
            instance.save()
            <b>go_next = request.GET.get('next', None)  # handle redirection
            if go_next:
                return redirect(go_next)</b>
            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)

Наконец добавьте, что TermAgreeMiddleware в MIDDLEWARE настройках. Поэтому каждый раз, когда вы хотите, чтобы пользователи согласовали новый термин, просто создайте новый экземпляр Term (с сайта администратора или из оболочки).

...