Python Django-如何使用复归

Python Django-如何使用复归,python,django,Python,Django,我正在攻读项目学位,我需要做一个像文档管理系统这样的应用程序。到目前为止,我一直在做一些事情,但我还需要对文档进行版本控制(当有人想要编辑文档时,首先需要下载文档,然后更新文档并作为现有文档的新版本上载).我读过关于Django恢复的内容,但不知道如何将其与我的应用程序集成到admin之外。我的代码可在此处找到: 有人能帮我吗 models.py import reversion from django.conf import settings from django.contrib.auth

我正在攻读项目学位,我需要做一个像文档管理系统这样的应用程序。到目前为止,我一直在做一些事情,但我还需要对文档进行版本控制(当有人想要编辑文档时,首先需要下载文档,然后更新文档并作为现有文档的新版本上载).我读过关于Django恢复的内容,但不知道如何将其与我的应用程序集成到admin之外。我的代码可在此处找到:

有人能帮我吗

models.py

 import reversion
from django.conf import settings
from django.contrib.auth.models import AbstractBaseUser, PermissionsMixin
from django.contrib.auth.models import (
    BaseUserManager, AbstractBaseUser
)
from django.core.mail import send_mail
from django.core.urlresolvers import reverse
from django.db import models
from django.db import models
from django.utils import timezone
from django.utils.http import urlquote
from django.utils.translation import ugettext_lazy as _
from django.utils.translation import ugettext_lazy as _


class CustomUserManager(BaseUserManager):
    def _create_user(self, email, password, is_staff, is_superuser, **extra_fields):
        """
        Creates and saves a User with the given email and password.
        """
        now = timezone.now()
        if not email:
            raise ValueError('The given email must be set')
        email = self.normalize_email(email)
        user = self.model(email=email,
                          is_staff=is_staff, is_active=True,
                          is_superuser=is_superuser, last_login=now,
                          date_joined=now, **extra_fields)
        user.set_password(password)
        user.save(using=self._db)
        return user

    def create_user(self, email, password=None, **extra_fields):
        return self._create_user(email, password, False, False,
                                 **extra_fields)

    def create_superuser(self, email, password, **extra_fields):
        return self._create_user(email, password, True, True,
                                 **extra_fields)


class CustomUser(AbstractBaseUser, PermissionsMixin):
    first_name = models.CharField(max_length=100, verbose_name=_("First name"))
    last_name = models.CharField(max_length=100, verbose_name=_("Last name"))
    email = models.EmailField(
        verbose_name='email address',
        max_length=255,
        unique=True,
    )
    date_of_birth = models.DateField(blank=True, null=True)
    date_joined = models.DateTimeField(_('date joined'), default=timezone.now)
    is_staff = models.BooleanField(_('staff status'), default=False,
                                   help_text=_('Designates whether the user can log into this admin '
                                               'site.'))
    is_active = models.BooleanField(_('active'), default=True,
                                    help_text=_('Designates whether this user should be treated as '
                                                'active. Unselect this instead of deleting accounts.'))

    objects = CustomUserManager()

    USERNAME_FIELD = 'email'
    REQUIRED_FIELDS = []

    def get_full_name(self):
        # The user is identified by their email address
        return u"%s %s" % (self.first_name, self.last_name)

    def get_short_name(self):
        # The user is identified by their email address
        return self.email

    def __unicode__(self):  # __unicode__ on Python 2
        return u"%s" % self.first_name

    class Meta:
        verbose_name = _("user")
        verbose_name_plural = _("users")


        # def has_perm(self, perm, obj=None):
        #     "Does the user have a specific permission?"
        #     # Simplest possible answer: Yes, always
        #     return True
        #
        # def has_module_perms(self, app_label):
        #     "Does the user have permissions to view the app `app_label`?"
        #     # Simplest possible answer: Yes, always
        #     return True

        # @property
        # def is_staff(self):
        #     "Is the user a member of staff?"
        #     # Simplest possible answer: All admins are staff
        #     return self.is_admin

@reversion.register
class Document(models.Model):
    name = models.CharField(max_length=70)
    owner = models.ForeignKey(CustomUser, on_delete=models.SET_NULL, null=True, related_name="created_by")
    type = models.CharField(max_length=50)
    keywords = models.TextField()
    description = models.TextField(default='some description')
    user = models.ForeignKey(CustomUser, on_delete=models.SET_NULL, null=True, related_name="working_user")
    creation_time = models.DateTimeField(auto_now_add=True)
    status = models.CharField(max_length=50)
    path = models.FileField(upload_to='media')
    folder = models.ForeignKey('Folder', on_delete=models.CASCADE, null=True)

    # version = models.ForeignKey('Version', on_delete=models.SET_NULL,null=True, related_name="version_id")

    def get_absolute_url(self):
        return reverse('DMS:detail', kwargs={'pk': self.pk})

        # def files(self):
        #     return u'<a href="%s%s" target="_blank">' % (settings.MEDIA_URL, self.files)

        # def __str__(self):
        #     return self.name+ '-' + self.type


class Version(models.Model):
    document = models.ForeignKey(Document, on_delete=models.SET_NULL, null=True)
    time = models.DateTimeField()
    user = models.ForeignKey(CustomUser, on_delete=models.SET_NULL, null=True, related_name="active_user")


class Folder(models.Model):
    name = models.CharField(max_length=100)

    root = models.CharField(max_length=50)

    def get_name(self):
        return "{}".format(self.name)
        # child = models.CharField(max_lenght = 20)

        # def get_absolute_url(self):
        # return reverse('DMS:folder-details', kwargs={'pk': self.pk})

    def get_absolute_url(self):
        return reverse('DMS:folder-details', kwargs={'pk': self.pk})

在admin之外,django恢复为您提供了两个选项:

  • :

  • A:

  • 这两个选项都要求您通过修饰的ModelAdmin类注册模型,或者:


    在admin之外,django恢复为您提供了两个选项:

  • :

  • A:

  • 这两个选项都要求您通过修饰的ModelAdmin类注册模型,或者:


    在这里添加代码。在这里添加代码。感谢您的回答@tutudaju。我选择使用视图装饰器/mixin选项。如果每次当用户希望上载对现有文档所做的更改时,我都要创建文档的新版本,那么我应该在类RevisionFormView中实现什么?据我所知,没有什么特别的。默认情况下,只要调用模型的
    save()
    方法,就应该创建一个版本。我已经更新了与问题代码相关的代码示例。顺便问一下@Liv52我曾经回答过你的问题吗?如果是,请将其标记为已解决。嗨@tutudaju,你在吗??需要帮助吗?谢谢你的回答@tutudaju。我选择使用视图装饰器/mixin选项。如果每次当用户希望上载对现有文档所做的更改时,我都要创建文档的新版本,那么我应该在类RevisionFormView中实现什么?据我所知,没有什么特别的。默认情况下,只要调用模型的
    save()
    方法,就应该创建一个版本。我已经更新了与问题代码相关的代码示例。顺便问一下@Liv52我曾经回答过你的问题吗?如果是,请将其标记为已解决。嗨@tutudaju,你在吗??需要帮助吗??
    import reversion
    from django.contrib.auth import authenticate, login, logout
    from django.db.models import Q
    from django.http import HttpResponseRedirect, HttpResponse, request
    from django.shortcuts import render, get_object_or_404
    from rest_framework import viewsets
    from rest_framework import permissions
    
    from .forms import FolderForm, DocumentForm
    from .models import Document, Folder
    from .serializers import DocumentSerializer
    
    
    def user_login(request):
        # If the request is a HTTP POST, try to pull out the relevant information.
        if request.method == 'POST':
            # Gather the username and password provided by the user.
            # This information is obtained from the login form.
            # We use request.POST.get('<variable>') as opposed to request.POST['<variable>'],
            # because the request.POST.get('<variable>') returns None, if the value does not exist,
            # while the request.POST['<variable>'] will raise key error exception
            email = request.POST.get('email')
            password = request.POST.get('password')
    
            # Use Django's machinery to attempt to see if the username/password
            # combination is valid - a CustomUser object is returned if it is.
            user = authenticate(email=email, password=password)
    
            # If we have a CustomUser object, the details are correct.
            # If None (Python's way of representing the absence of a value), no user
            # with matching credentials was found.
            if user:
                # Is the account active? It could have been disabled.
                if user.is_active:
                    # If the account is valid and active, we can log the user in.
                    # We'll send the user back to the homepage.
                    login(request, user)
                    return HttpResponseRedirect('/DMS/first/')
                else:
                    # An inactive account was used - no logging in!
                    return HttpResponse("Your DMS account is disabled.")
            else:
                # Bad login details were provided. So we can't log the user in.
                print("Invalid login details: {0}, {1}".format(email, password))
                return HttpResponse("Invalid login details supplied.")
    
        # The request is not a HTTP POST, so display the login form.
        # This scenario would most likely be a HTTP GET.
        else:
            # No context variables to pass to the template system, hence the
            # blank dictionary object...
            return render(request, 'DMS/login.html', {})
    
    
    def user_logout(request):
        # Since we know the user is logged in, we can now just log them out.
        logout(request)
    
        # Take the user back to the homepage.
        return HttpResponseRedirect('/DMS/login/')
    
    
    def index(request):
        folder_name = Folder.objects.all()
    
        context = {
    
            'folder_name': folder_name,
        }
    
        return render(request, 'DMS/index.html', context)
    
    
    #
    # def remove(request, post_id):
    #     try:
    #         folder_id = Folder.objects.get(pk=question_id)
    #         folder_id.remove()
    #     except Folder.DoesNotExist:
    #         raise Http404("Error 404")
    #     return render(request, 'index.html', {'message': 'Folder was removed'})
    
    
    
    def FolderDetail(request, pk):
        folder = get_object_or_404(Folder, pk=pk)
        folder_name = Folder.objects.all()
        # document_list = Document.objects.all()
        # query = request.GET.get("q")
        # if query:
        #     document_list = document_list.filter(Q(keywords__icontains=query)).distinct()
        #     return render(request, 'DMS/folder-details.html', {'document_list': document_list})
    
        context = {
            'folder': folder,
            'folder_name': folder_name,
            # 'document_list': document_list
        }
    
        return render(request, "DMS/folder-details.html", context)
    
    
    # class FolderDetailsView(generic.DetailView):
    #     model = Folder
    #     template_name = 'DMS/folder-details.html'
    
    
    def DocumentView(request):
        document_list = Document.objects.all()
        query = request.GET.get("q")
        if query:
            document_list = document_list.filter(Q(keywords__icontains=query)).distinct()
            return render(request, 'DMS/documents.html', {'document_list': document_list})
    
        return render(request, 'DMS/documents.html', {'document_list': document_list})
    
    
    def create_document(request, folder_id):
        # form = forms.DocumentForm()
        form = DocumentForm(request.POST or None, request.FILES or None)
        folder = get_object_or_404(Folder, pk=folder_id)
        # foldern = get_object_or_404(Folder,)
        folder_name = Folder.objects.all()
        if form.is_valid():
            folder_document = folder.document_set.all()
            for d in folder_document:
                if d.name == form.cleaned_data.get("name"):
                    context = {
                        'folder': folder,
                        'form': form,
                        'folder_name': folder_name,
                        'error_message': 'You already added that document',
                    }
                    # return HttpResponseRedirect('/DMS/folder-details')
                    return render(request, 'DMS/folder-details.html', context)
            document = form.save(commit=False)
            document.folder = folder
            document.save()
            return HttpResponseRedirect('/DMS/' + folder.id)
        context = {
            'folder': folder,
            'form': form,
            'folder_name': folder_name
        }
        return render(request, 'DMS/create_document.html', context)
    
    
    def create_folder(request):
        form = FolderForm(request.POST or None, request.FILES or None)
        folder_name = Folder.objects.all()
        if form.is_valid():
            folder = form.save(commit=False)
            folder.save()
    
            return HttpResponseRedirect('/DMS/first')
        context = {
            "form": form,
            "folder_name": folder_name
        }
    
        return render(request, 'DMS/create_folder.html', context)
    
    
    def delete_document(request, folder_id, document_id):
        folder = get_object_or_404(Folder, pk=folder_id)
        folder_name = Folder.objects.all()
        document = Document.objects.get(pk=document_id)
        document.delete()
        context = {
            "folder": folder,
            "folder_name": folder_name
        }
        return render(request, 'DMS/folder-details.html', context)
    
    
    def delete_folder(request, pk):
        folder = Folder.objects.get(pk=pk)
        folder_name = Folder.objects.all()
        for f in folder_name:
            if f.id == folder.id:
                if f.root == 'root':
                    for child in folder_name:
                        if child.root == folder.name:
                            child.delete()
                            folder.delete()
                            # folder.delete(name= folder)
                            #     if f.root == folder.name:
                            #         folder.delete(root = folder)
                        else:
                            folder.delete()
    
                else:
                    folder.delete()
    
                    # for child in folder_name:
                    #     if child.root == f.name:
                    #         child.delete()
                    #         # folder.delete()
    
        return render(request, 'DMS/folder-details.html', {'folder': folder, 'folder_name': folder_name})
    
    class DocumentViewSet(viewsets.ModelViewSet):
        queryset = Document.objects.all()
        serializer_class = DocumentSerializer
        permission_classes = (permissions.IsAuthenticatedOrReadOnly)
    
    with reversion.create_revision():
        obj = Document()
        obj.name = "obj v1"
        obj.save()
    
        reversion.set_user(request.user)
        reversion.set_comment("Created revision 1")
    
    from django.conf.urls import url
    from rest_framework.urlpatterns import format_suffix_patterns
    
    from . import views
    from django.conf.urls import include
    
    app_name = 'DMS'
    
    
    
    urlpatterns = [
        url(r'^first/$', views.index, name='index'),
        # url(r'^document/add/$', views.DocumentCreate.as_view(), name='document-add'),
        # url(r'^(?P<pk>[0-9]+)/$', views.DetailView.as_view(), name='detail'),
        url(r'^(?P<pk>[0-9]+)/$', views.FolderDetail, name='folder-details'),
        # url(r'^folder/add/$', views.FolderCreate.as_view(), name='folder-add'),
        url(r'^(?P<folder_id>[0-9]+)/create_document/$', views.create_document, name='create_document'),
        url(r'^create_folder/$', views.create_folder, name='create-folder'),
        url(r'^login/$', views.user_login, name='user_login'),
        url(r'^logout/$', views.user_logout, name='user_logout'),
        url(r'^doc/$', views.DocumentView, name='document'),
        url(r'^(?P<folder_id>[0-9]+)/delete_document/(?P<document_id>[0-9]+)/$', views.delete_document,
            name='delete_document'),
        url(r'^(?P<pk>[0-9]+)/delete_folder/$', views.delete_folder, name='delete_folder'),
    
    
    ]
    
    urlpatterns = format_suffix_patterns(urlpatterns)
    
    from django import forms
    
    from .models import Folder, Document, CustomUser
    
    
    class DocumentForm(forms.ModelForm):
        EXTENSIONS = (('jpg', 'jpg'),
                      ('pdf', 'pdf'),
                      ('png', 'png'),
                      ('docx', 'docx'),
                      ('pptx', 'pptx'),
                      ('xls', 'xls'),
                      )
    
        type = forms.ChoiceField(choices=EXTENSIONS)
        class Meta:
            model = Document
            fields = ['name', 'owner', 'type', 'keywords', 'description', 'path']
    
    
    class FolderForm(forms.ModelForm):
        CHOICES = [[x.name, x.name] for x in Folder.objects.all()]
    
        CHOICES.insert(0, ['root', "Root Folder"])
        root = forms.ChoiceField(choices=CHOICES)
    
        class Meta:
            model = Folder
            fields = ['name', 'root']
    
    
    class UserForm(forms.ModelForm):
        class Meta:
            model = CustomUser
            fields = ['email', 'password']
    
    MIDDLEWARE += ('reversion.middleware.RevisionMiddleware')
    
    from reversion.views import RevisionMixin
    
    class DocumentViewSet(RevisionMixin, viewsets.ModelViewSet):
         queryset = Document.objects.all()
         serializer_class = DocumentSerializer
         permission_classes = (permissions.IsAuthenticatedOrReadOnly)
    
    @reversion.register
    class Document(models.Model):
        # ... rest of definition
        pass