Как применить разрешения на чтение / запись к загруженным пользователем файлам в Django

#python #django #authentication #permissions

#python #django #аутентификация #разрешения

Вопрос:

У меня есть модель «document», система загрузки, использующая dropzone.js и регистрация / вход в систему. Теперь я не понимаю, как применять разрешения к каждому отдельному загруженному файлу, чтобы только указанные пользователи могли получить к ним доступ.

В основном: File1-> accessible_by = user1, user2

File2-> accesible_by= user3, user5…

И так далее.

Спасибо всем за советы / помощь по моей проблеме.

Редактировать с помощью соответствующего кода:

Создать представление документа:

 class DocumentCreate(CreateView):
    model = Document
    fields = ['file', 'is_public']

    def form_valid(self, form):
        self.object = form.save()
        data = {'status': 'success'}
        response = JSONResponse(data, mimetype =
        response_mimetype(self.request))
        return response
  

Я сделал выше для представления для обработки dropzone.js загрузка файлов.

Это моя модель «документа»

 class Document(models.Model):

    file = models.FileField(upload_to = 'files/')
                                #validators=[validate_file_type])
    uploaded_at = models.DateTimeField(auto_now_add = True)
    extension = models.CharField(max_length = 30, blank = True)
    thumbnail = models.ImageField(blank = True, null = True)
    is_public = models.BooleanField(default = False)

    uploaded_by = models.ForeignKey(User,
                                related_name='uploadedByAsUser', null=True)

    allowed_users = models.ManyToManyField(User,
                                related_name='allowedUsersAsUser')

    def clean(self):
        self.file.seek(0)
        self.extension = self.file.name.split('/')[-1].split('.')[-1]
        if self.extension == 'xlsx' or self.extension == 'xls':
            self.thumbnail = 'xlsx.png'
        elif self.extension == 'pptx' or self.extension == 'ppt':
            self.thumbnail = 'pptx.png'
        elif self.extension == 'docx' or self.extension == 'doc':
            self.thumbnail = 'docx.png'


    def delete(self, *args, **kwargs):
        #delete file from /media/files
        self.file.delete(save = False)
        #call parent delete method.
        super().delete(*args, **kwargs)

    #Redirect to file list page.
    def get_absolute_url(self):
        return reverse('dashby-files:files')

    def __str__(self):
        return self.file.name.split('/')[-1]

    class Meta():
        ordering = ['-uploaded_at']
  

Ответ №1:

Вы можете добавить allowed_user поле в модель документа, чтобы только указанные пользователи могли получить доступ к файлам. например:

 class Document(models.Model):
    file = FileField()
    uploaded_by = models.ForeignKey(User, related_name='uploadedByAsUser')
    allowed_users = models.ManyToManyField(User, related_name='allowedUsersAsUser')
  

Таким образом, если вы хотите, чтобы пользователь был добавлен в список «разрешенных», вы можете просто добавить их, используя что-то вроде этого:

 class DocumentCreate(CreateView):
    model = Document
    fields = ['file', 'is_public']

    def form_valid(self, form):
        self.object = form.save(commit=False)
        self.object.allowed_users.add(request.user)
        self.object.save()
        data = {'status': 'success'}
        response = JSONResponse(data, mimetype =
        response_mimetype(self.request))
        return response
  

Затем, чтобы администратор выглядел красиво (admin.py ):

 class DocumentAdmin(admin.ModelAdmin):
    list_display = ('uploaded_by', 'file')

    fields = ('id', 'file', 'uploaded_at', 'extension', 'thumbnail', 'is_public', 'uploaded_by', 'allowed_users')
    filter_horizontal = ('allowed_users',)

    readonly_fields = ('id',)

admin.site.register(Document, DocumentAdmin)
  

Затем, если вы хотите проверить, разрешены ли они, вы можете сделать:

 if allowed_user in doc.allowed_users:
    print('We have liftoff')
  

Комментарии:

1. Я пытался использовать ManyToManyField, но всякий раз, когда я загружал файл, каждая учетная запись пользователя, созданная в базе данных, автоматически добавлялась в allowed_users без моих действий, а также я не мог получить доступ к фактическим данным и изменить их.

2. Кроме того, при добавлении uploaded_by и allowed_users в модель я получаю сообщение об ошибке, в котором говорится, что у меня не может быть 2 полей с одним и тем же связанным объектом.

3. Я добавил related_name поле, чтобы исправить ошибку, указанную в вашем втором комментарии, что касается вашего первого комментария, пожалуйста, будьте немного конкретнее. Можете ли вы показать мне код представления? Может быть, вы случайно перебираете всех пользователей и добавляете их в allowed_users ?

4. Да, извините, я думаю, я слишком расплывчатый. Я обновил сообщение соответствующим кодом. Спасибо за первое исправление, не знал о связанном имени. Может быть, это делает CreateView, от которого я наследую? не совсем уверен.

5. Хорошо, отлично, теперь вопрос: итак, вы говорите, что когда вы просматриваете DocumentCreate представление, allowed_users оно заполняется ВСЕМИ пользователями в базе данных?

Ответ №2:

Вы можете установить content_type для HttpResponse. Таким образом, вы можете выполнять обработку разрешений в своем представлении и обслуживать файл непосредственно из Django:

 return HttpResponse("Text only, please.", content_type="text/plain")
  

Примечание: Django не является веб-сервером. Рекомендуется использовать веб-сервер для обслуживания статических файлов!

Приведенный выше метод может быть хорошим подходом, если вы обрабатываете небольшие объемы данных и только случайно обрабатываете данные. Если вам нужно надежное решение, вам нужно проверить разрешения в Django и оставить отправку данных на веб-сервер.

  • Lighthttpd X-Sendfile
  • Внутренние перенаправления Apache mod_wsgi
  • NGNIX X-Ускорение-перенаправление

Взгляните на пакеты потоковой передачи файлов Django: https://djangopackages.org/grids/g/file-streaming /

Комментарии:

1. Я использую Apache с mod_wsgi, но я не знаю, обслуживаю ли я файлы через Apache или Django, что довольно ново для серверной части и веб-разработчиков в целом. На самом деле мне нужно постоянно загружать файлы, поэтому мне было бы интересно использовать Apache для обслуживания файлов и использовать разрешения django, но я не могу понять это прямо сейчас. Как мне поступить?

2. Итак, небольшая поправка. Я уже обслуживаю статические файлы через Apache, поэтому хотел бы знать, как поступить с разрешениями django, спасибо 🙂