在Django中get_object_or_404总是返回404

1 投票
2 回答
903 浏览
提问于 2025-04-18 11:36

这是我的 urls.py 文件

url(r'^file/(?P<filename>.*)$', 'notendur.views.file', name="file"),

这是我的 views.py 文件

@login_required
def file(request, filename):
    file = get_object_or_404(Document, user=request.user, filename=filename)
    return sendfile(request, file.docfile.path)

这是我的 models.py 文件

fs = FileSystemStorage(location=settings.UPLOAD_ROOT)

class Document(models.Model):
    filename = models.CharField(max_length=255, blank=False, null=False, default="")
    upload_path = models.CharField(max_length=255, blank=False, null=False, default="")
    user = models.ForeignKey(User, null=False)
    docfile = models.FileField(upload_to=_upload_path, storage=fs)
    options = models.IntegerField(default=0)

    def get_upload_path(self,filename):
        return "uploads/"+str(self.user.id) + '/' + str(date.today()) + '/' + filename

我的问题是,尽管文件路径是正确的,但我总是收到404错误。我怀疑是我的 get_object_or_404 函数出了问题。

补充说明:

这些文件实际上在 file/uploads/<primary_key>/<upload_date>/ 这个路径下!抱歉之前没有提到。请问什么样的正则表达式可以匹配这种链接呢?

2 个回答

0

如果filename是正确的,那么看起来user不匹配。这个视图只允许文件的拥有者访问;这样理解对吗?如果是这样的话,你应该返回一个403错误:

@login_required
def file(request, filename):
    file = get_object_or_404(Document, filename=filename)
    if file.user != request.user:
        return HttpResponseForbidden()
    return sendfile(request, file.docfile.path)

假设用户的ID是5,他们尝试访问file/test_file,这个文件是在2014年6月30日上传的。那么filename == 'test_file',匹配的记录应该有以下字段:

filename: "test_file"
upload_path: "uploads/5/2014-06-30/test_file"
user: <User with id: 5>
docfile.path: "uploads/5/2014-06-30/test_file"

这和你在磁盘上或数据库中看到的匹配吗?

0

你可以试试用一个查询集:

queryset = Document.objects.filter(user=request.user, filename=filename)
get_object_or_404(queryset)

你也可以打印一些值,看看能不能找到问题所在:

print request.user
print filename

另外,你在网址中接受空字符串作为文件名(通过使用 *)。为什么不使用 "+" 呢?:

url(r'^file/(?P<filename>.+)$', 'notendur.views.file', name="file"),

如果你需要的话,这里有一些参考资料的列表:

# Regular references:
# . any char
# ^ start of string
# $ end of string
# * 0 or more of preceding
# + 1 or more of preceding
# ? 0 or 1 of preceding
# (?!..) matches when it doesnt match ..
# *? 0 or more, minimal match
# +? 1 or more, minimal match
# {m} exactly m of preceding
# {m,n} between m to n of preceding
# [..] eg. [abc],[a-z],[0-9a-z]
# [^..] matches if doesn't match [..]
# (..) groups what's inside
# (?=..) matches .. but doesn't consume it
# \d [0-9] (decimal digit)
# \D [^0-9] (non-digit)
# \w [a-zA-Z0-9_] (alphanumeric)
# \W [^a-zA-Z0-9_] (non-alphanumeric)
# \s [ \t\n\r\f\v] (whitespace)
# \S [^ \t\n\r\f\v] (non-whitespace)

撰写回答