我使用amazon s3存储上传的用户图片。我的问题是:
所以,我的问题是,我该怎么办才能让我网站的用户上传,下载和删除内容?
因为我有条件:
models.py:
def get_upload_file_name(instance, filename):
return "uploaded_files/%s_%s" %(str(time()).replace('.','_'), filename)
PRIVACY = (
('H','Hide'),
('F','Followers'),
('A','All'),
)
class Status(models.Model):
body = models.TextField(max_length=200)
image = models.ImageField(blank=True, null=True, upload_to=get_upload_file_name)
privacy = models.CharField(max_length=1,choices=PRIVACY, default='F')
pub_date = models.DateTimeField(auto_now_add=True, auto_now=False)
user = models.ForeignKey(User)
settings.py:
DEFAULT_FILE_STORAGE = 'storages.backends.s3boto.S3BotoStorage'
AWS_ACCESS_KEY_ID = 'FAKEAMAZONKEY'
AWS_SECRET_ACCESS_KEY = 'FAKEAMAZONSECRETKEY'
AWS_STORAGE_BUCKET_NAME = 'fakebucketname'
更新
用户之间关系模型
class Person(models.Model):
user = models.OneToOneField(User)
relationships = models.ManyToManyField('self', through='Relationship',
symmetrical=False,
related_name='related_to')
def __unicode__(self):
return self.user.username
def add_relationship(self, person, status):
relationship, created = Relationship.objects.get_or_create(
from_person=self,
to_person=person,
status=status)
return relationship
def remove_relationship(self, person, status):
Relationship.objects.filter(
from_person=self,
to_person=person,
status=status).delete()
return
def get_relationships(self, status):
return self.relationships.filter(
to_people__status=status,
to_people__from_person=self)
def get_related_to(self, status):
return self.related_to.filter(
from_people__status=status,
from_people__to_person=self)
def get_following(self):
return self.get_relationships(RELATIONSHIP_FOLLOWING)
def get_followers(self):
return self.get_related_to(RELATIONSHIP_FOLLOWING)
def get_friends(self):
return self.relationships.filter(
to_people__status=RELATIONSHIP_FOLLOWING,
to_people__from_person=self,
from_people__status=RELATIONSHIP_FOLLOWING,
from_people__to_person=self)
RELATIONSHIP_FOLLOWING = 1
RELATIONSHIP_BLOCKED = 2
RELATIONSHIP_STATUSES = (
(RELATIONSHIP_FOLLOWING, 'Following'),
(RELATIONSHIP_BLOCKED, 'Blocked'),
)
class Relationship(models.Model):
from_person = models.ForeignKey(Person, related_name='from_people')
to_person = models.ForeignKey(Person, related_name='to_people')
status = models.IntegerField(choices=RELATIONSHIP_STATUSES)
def __unicode__(self):
return "%s %s %s" % (self.from_person, self.get_status_display(), self.to_person)
class Activity(models.Model):
actor = models.ForeignKey(User)
action = models.CharField(max_length=100)
content_type = models.ForeignKey(ContentType, related_name="content_type")
object_id = models.PositiveIntegerField()
content_object = generic.GenericForeignKey('content_type', 'object_id')
element_type = models.ForeignKey(ContentType, related_name="element_type", blank=True, null=True)
element_id = models.PositiveIntegerField(blank=True, null=True)
element_object = generic.GenericForeignKey('element_type', 'element_id')
pub_date = models.DateTimeField(auto_now_add=True, auto_now=False)
class Meta:
verbose_name = 'Activity'
verbose_name_plural = 'Activities'
ordering = ['-pub_date']
def __unicode__(self):
return ("%s %s") % (self.actor.username, self.action)
def get_rendered_html(self, user=None):
if self.element_type:
template_name = '%s_activity.html' %(self.element_type.name)
else:
template_name = '%s_activity.html' %(self.content_type.name)
return render_to_string(template_name, {
'object':self.content_object,
'actor':self.actor,
'action':self.action,
'element_object':self.element_object,
'user':user,
'pub_date':self.pub_date
})
答案 0 :(得分:5)
直接加载文件时,您可以使用Amazon's Query String Authentication,其中必须在URL中包含签名,以验证您是否可以获取文件。
您的应用可以使用boto' Key.generate_url
method来创建此类网址。您还应该添加一个到期时间,之后链接将不再有效。
编辑:关于如何使用boto ,,,
进行更详细的description答案 1 :(得分:2)
正如乔治所说,你需要采取两个步骤来完成这项工作,虽然不是授予对ec2实例的访问权限(从未使用过该方法),我建议只授予你特定密钥的权限(广泛使用这种方法)< / p>
以下是关于权限如何工作的亚马逊。它们并不简单,因此您需要了解主要帐户是谁,以及您是否使用其密钥或IAM用户的密钥。无论如何,你的密钥应该可以完全访问资源(希望它是你的桶,而不是其他人,因为事情稍微复杂一些) http://docs.aws.amazon.com/AmazonS3/latest/dev/s3-access-control.html
用于创建资源: - 如果您提供的后端有效,并且您已经很好地配置了S3权限,那么您不应该做任何事情。但是,要检查您的密钥不是问题,请执行以下操作:
from boto.s3.connection import S3Connection as s3c
connection = s3c('your-aws-access-key', 'your-aws-secret-key')
bucket = connection.get_bucket('your-bucket-name')
new_key = bucket.new_key('your-key-name') #meaning the name of the file
# https://github.com/boto/boto/blob/develop/boto/s3/bucket.py#L611
new_key.send_file(file_object) #this will upload the file
# https://github.com/boto/boto/blob/develop/boto/s3/key.py#L709
如果一切正常,您应该能够在S3浏览器中看到您的文件 - 如果没有,您将不得不返回有关S3访问权限的文档。
仅允许关注用户X的用户访问用户上传的文件:
您的models.py
文件并未说明您是如何实施follow
逻辑的。我无法告诉谁是谁。您有自己的自定义User
型号吗?你使用Django,但有扩展吗?你有自己的模型链接用户吗?分享有关用户如何遵循&#39;的更多信息。另一个,然后我甚至可以共享代码片段。
允许用户X删除自己的文件: 我猜测Status.user字段已经包含对创建图像的用户的引用。如果是这样:将其放在您的视图中:
def picture_deletion_view(request, status_identifier ...):
try:
status = Status.objects.filter(id_or_some_identifier=status_identifier)
except Status.DoesNotExist:
return SomeHttpResponse()
if request.user.id == status.user.id:
# you can delete the picture and redirect... to somewhere
else:
# you can't delete! redirect...or something
答案 2 :(得分:1)
这是由视图和模板处理的逻辑。
例如,在模板中,您可以使用带有uploadform的此{% if user.is_authenticated %}
块,并且在视图中您还可以检查用户是否经过身份验证,然后才将您的内容加载到s3
答案 3 :(得分:1)
所以我不能和aws.s3说话,但对于django来说,限制谁有权访问视图的最佳方法是要求通过django的login_required
装饰者登录:
from django.contrib.auth.decorators import login_required
@login_required
def my_view(request):
...
或者,如果你想公开所有的视图,而不是公开页面的部分(链接等),你可以把这些信息放到模板中,就像@t_io所说的那样,但django docs强烈建议不要放置模板中的处理逻辑很多,因为它会减慢网站的速度。将这些信息放在视图中会更好:
@login_required
def image_view(request):
user = request.user
# this list has the user's own images
mine = []
for status in user.status_set.all():
mine.append(status.image)
# this list has the images the user can see (relationship-based)
following = []
friends = []
# you can get the person from the user
person = user.person
for status in person.get_friends().all():
friends.append(status.image)
for status in person.get_following().all():
following.append(status.image)
ctx = dict(user=request.user, friends=friends, following=following, mine=mine)
return render("template.html", ctx)
并在模板中,您可以遍历列表
{% for img in mine %}
<li><a href=...></a></li>
{% endfor %}
{% for img in following %}
<li><a href=...></a></li>
{% endfor %}
......你明白了
为了防止人们直接导航到媒体网址,你可以使用sendfile(python库)或apache / nginx等价物。所以你需要另一个观点:
import sendfile
from django.conf import settings
@login_required
def handle_media(request, path=None):
try:
requested_file = os.path.join(settings.MEDIA_ROOT, path)
return sendfile.sendfile(request, requested_file)
except:
pass
return HttpResponseNotFound('<h1>Page not found {}</h1>'.format(path))
然后你需要一个额外的网址(urls.py):
urlpatterns = patterns('',
url(r'/media/(?P<path>[a-zA-Z0-9_- /]+)$', views.handle_media),
)
请参阅django-sendfile以了解sendfile
答案 4 :(得分:0)
由于boto3退出,我们可以使用: https://github.com/boto/boto3/blob/develop/docs/source/guide/s3-presigned-urls.rst
ELISP> (replace-regexp "war" "negotiation" "trade war")
nil
ELISP>
我们也可以使用类似的方法在同一引用链接中上传对象。