0

我正在尝试使用上传图像制作应用程序。问题是我想限制每天只能上传一次图片的可能性。除非用户使用浏览器的后退按钮,否则一切正常。他可以垃圾邮件系统。什么是防止这种情况的正确方法?Django CreateView允许在按下后退按钮时显示表单时重新提交数据

models.py

# Admin option to select from 
PHOTO_STATUS = (
    ('ir', 'In Review'), 
    ('ap', 'Approved'), 
    ('tr', 'Trash'), 
) 

def pause(): 
    return timezone.now() + timezone.timedelta(minutes=5) 


# Main photo upload app 
class PhotoUpload(models.Model): 
    '''After the user finishes the challenge 
    he can upload a photo using this app''' 
    # The date when a user uploads a photo 
    date_upload = models.DateTimeField(default=timezone.now) 
    # The date when user can upload another photo 

    # pause = date_upload + timezone.timedelta(minutes=20) 
    pause_upload = models.DateTimeField(default=pause) 
    # The status of the photo 
    status = models.CharField(max_length=2, default='ir', choices=PHOTO_STATUS) 
    # The date when the admin aproves the photo 
    date_approved = models.DateTimeField(default=timezone.now, 
             blank=True, 
             null=True) 
    # The date when the admin soft-deletes the photo 
    date_deleted = models.DateTimeField(default=timezone.now, 
             blank=True, 
             null=True) 
    user = models.ForeignKey(User) 

    # A function that defines the path where the photo 
    # will be uploaded and that will change the filename. 
    def path_and_rename(instance, filename): 
     extension = filename.split('.')[-1] 
     if User.is_authenticated: 
      # print(instance._user.username) 
      return 'uploads/{}-{}.{}'.format(instance.user.username, 
              instance.date_upload, 
              extension) 
     else: 
      return 'uploads/{}.{}'.format(instance.date_upload, extension) 

    # Application side file size check 
    def file_size(value): 
     limit = 2 * 1024 * 1024 
     if value.size > limit: 
      raise ValidationError(
       'File too large. Size should not exceed 2 MB.') 

    image = models.ImageField(upload_to=path_and_rename, 
           validators=[file_size], 
           null=True, 
           blank=True) 

    def __str__(self): 
     return str(self.pause_upload) 

视图

class PhotoUploadCreate(CreateView): 
    model = PhotoUpload 
    template_name = 'upload_photo.html' 
    form_class = PhotoUploadForm 

    def form_valid(self, form): 
     form.instance.user = self.request.user 
     return super(PhotoUploadCreate, self).form_valid(form) 

    def get_success_url(self): 
     return reverse('success') 

谢谢!

编辑 这里是我的模板,我使用了一个名为照片模板标签和一个称为模板过滤经过

{% for photo in photos %} 

    <div class="container vertical-centre"> 

     {% if not photo.pause_upload|elapsed:1 %} 

      <div class="row"> 
       <div class="col-md-8 col-md-offset-2"> 
        <h1 class="centre-colour"> 
         {% if photo.user.first_name %}{{ photo.user.first_name }}{% else %}{{ photo.user.username }}{% endif %} you can upload another photo anytime after:<br> 
          <div id="clockdiv" class="centre-colour"> 
    <span class="hours"></span> Hours <span class="minutes"></span> minutes 
    <span class="seconds"></span> seconds 
</div> 
        </h1> 
       </div> 
      </div> 

     {% else %} 

      <div class="row"> 
       <div class="col-md-8 col-md-offset-2"> 
        <h1 class="centre-colour"> 
         CONGRATULATIONS {% if photo.user.first_name %}{{ photo.user.first_name }}{% else %}{{ photo.user.username }}{% endif %}!!! 
        </h1> 
        <h2 class="centre-colour"> 
         Upload photo: 
        </h2> 
       </div> 
      </div> 

      <div class="row"> 
       <div class="col-md-8 col-md-offset-2"> 
        <form action="" method="POST" enctype="multipart/form-data"> 
        {% csrf_token %} 
         <div class="form-group"> 
         {% crispy form %} 
         </div> 
        </form> 
        <h4 class="centre-colour">or</h4> 
        <a href="{% url 'home' %}" role="button" id="goHome" class="btn btn-primary btn-block">Start again</a> 
       </div> 
      </div> 

     {% endif %} 
    </div> 
{% endfor %} 

而且这里的模板标签和过滤

register = template.Library() 
@register.inclusion_tag('photos/photos_tags.html') 
def photos_up(request, number=1): 
    a = PhotoUpload.objects.filter(user__username=request).exists() 
    if a: 
     return {'form': PhotoUploadForm(), 
       'photos': PhotoUpload.objects.filter(
        user__username=request 
     ).order_by(
        '-pause_upload')[:number] 
     } 
    else: 
     return {'form': PhotoUploadForm(), 
       'photos': PhotoUpload.objects.all()[:number] 
       } 

register = template.Library() 
@register.filter(expects_localtime=True) 
def elapsed(time, seconds): 
    return time + timezone.timedelta(seconds=seconds) < timezone.now() 

一切工作正常,除非用户决定从成功页面点击后退按钮。然后上传页面将再次进入窗体视图,而不是去柜台。

+0

如果时间增量(使用当前时间)少于一天,您可以保存上次上传图像的时间戳并禁用上传。 – utkbansal

+0

你可以考虑限制访问...这里是一个可能的插件https://django-ratelimit.readthedocs.io/en/v1.0.0/ – micebrain

+0

@utkbansal谢谢你的评论。请参阅我的更新。 – Dragos

回答

0

您可以将数据库中的属性设置为lastuploaded (DateTimeField),当用户上传照片时,检查lastuploaded是否是当前时间的前一天。 编辑: 添加最后上传的字段到您的模型。

class PhotoUpload(models.Model): 
    last_uploaded = models.DateTimeField(null=True, blank=True, default=timezone.now) 

现在在你的视图的form_valid函数中加上一个检查。

def form_valid(self, form): 
     photo_upload_object = PhotoUpload.objects.filter(user=self.request.user).latest('last_uploaded') 
     if photo_upload_object.last_uploaded + datetime.datetime.timedelta(days=1) < current_time and photo_upload_object.last_uploaded is not None: 
      form.instance.user = self.request.user 
      return super(PhotoUploadCreate, self).form_valid(form) 
     else: 
      return HttpResponse("some error") 

其他的方法可能是保存上次上传的cookies,但不会在所有情况下都可以使用,如从不同设备登录。

+0

感谢您的评论。请参阅我的更新。 – Dragos

+0

你为什么要用模板标签做这个。当用户上传请求到达服务器时,请检查'current_time> UserObject.lastuploaded + 1 day'(伪代码)。并且为此目的不要在您的模板中使用任何日期时间字段。这将是多余的。 –

+0

我是一名初学者,并且我更容易在模板标记中创建逻辑,而不是在CreateView中创建逻辑。我知道这并不尊重DRY概念,但它是唯一有效的工具。并且正在工作,除非用户点击后退按钮。在部署之前,我会做一个代码重构。 – Dragos

相关问题