Python 最初以Django形式填充文件字段
我有一个描述网页的模型。Python 最初以Django形式填充文件字段,python,django,django-class-based-views,Python,Django,Django Class Based Views,我有一个描述网页的模型。source\u upload字段表示网页的屏幕截图 为了将站点对象添加到我的应用程序中,我使用了基于django类的CreateView。这真的很有效 现在我正在尝试添加一种半自动的添加站点的方法。您可以向视图传递URL,视图会自动填充表单(并生成网页的屏幕截图)。用户应该能够查看所有自动提取的字段-尤其是自动生成的屏幕截图图像-更改它们并点击保存按钮将对象添加到数据库中,并将图像(如果批准)添加到其最终位置 我试图在视图的get\u initial方法中实现这一点。除
source\u upload
字段表示网页的屏幕截图
为了将站点对象添加到我的应用程序中,我使用了基于django类的CreateView
。这真的很有效
现在我正在尝试添加一种半自动的添加站点的方法。您可以向视图传递URL,视图会自动填充表单(并生成网页的屏幕截图)。用户应该能够查看所有自动提取的字段-尤其是自动生成的屏幕截图图像-更改它们并点击保存按钮将对象添加到数据库中,并将图像(如果批准)添加到其最终位置
我试图在视图的get\u initial
方法中实现这一点。除了屏幕截图-FileField
,这项功能非常有效。我在initial['source\u upload']
中设置的路径未显示在表单的FileInput小部件的current:
部分中
如何给文件字段一个初始值?
型号.py
class Site(models.Model):
def get_source_upload_path(instance, filename):
now = datetime.datetime.now()
return "appname/sites/{}/{}/{}/site_{}_{}".format(now.year, now.month, now.day, instance.pk, filename)
creationDate = models.DateTimeField(auto_now_add=True)
last_modifiedDate = models.DateTimeField(auto_now=True)
creator = models.ForeignKey('auth.User', related_name='siteCreated')
last_modifier = models.ForeignKey('auth.User', related_name='siteLast_modified')
date = models.DateTimeField(default=datetime.date.today)
title = models.CharField(max_length=240, blank=True)
body = models.TextField(max_length=3000)
source_url = models.URLField(blank=True)
source_upload = models.FileField(upload_to=get_source_upload_path, blank=True)
keywords = models.ManyToManyField("Keyword")
url(r'site/add/$', views.SiteCreate.as_view(), name='site-add'),
url(r'site/add/(?P<source_url>[A-Za-z0-9\-._~:/\[\]@!$&\'\(\)\*\+,;=?#]+)/$', views.SiteCreate.as_view(), name='site-add-fromurl'),
class SiteForm(ModelForm):
class Meta:
model = Site
fields = ['date', 'title', 'body', 'source_url', 'source_upload', 'keywords']
widgets = {
'keywords' : CheckboxSelectMultiple(),
}
class SiteCreate(LoginRequiredMixin, CreateView):
model = Site
template_name = 'appname/site_form.html'
form_class = SiteForm
success_url = reverse_lazy('appname:index')
def form_valid(self, form):
form.instance.creator = self.request.user
form.instance.last_modifier = self.request.user
return super(SiteCreate, self).form_valid(form)
def get_initial(self):
# Get the initial dictionary from the superclass method
initial = super(SiteCreate, self).get_initial()
try:
#get target url from request
fullpath = self.request.get_full_path()
fullpath = fullpath.split("/")
fullpath, querystring = fullpath[3:-1], fullpath[-1]
source_domain = fullpath[2]
fullpath = "/".join(fullpath)
fullpath += querystring
source_url = fullpath
if (not source_url.startswith("http://") and not source_url.startswith("https://")):
print("ERROR: url does not start with http:// or https://")
return initial
# ...
# extract title, date & others with BeautifulSoup
# ...
#extract screenshot (is there a better way?)
from selenium import webdriver
driver = webdriver.Firefox()
driver.get(source_url)
tmpfilename = "{}_{}.png".format(get_valid_filename(source_domain), get_valid_filename(title[:30]))
now = datetime.datetime.now()
tmpfilepath_rel = "appname/sites/tmp/{}/{}/{}/{}".format(now.year, now.month, now.day, tmpfilename)
tmpfilepath = settings.MEDIA_ROOT + tmpfilepath_rel
folder=os.path.dirname(tmpfilepath)
if not os.path.exists(folder):
os.makedirs(folder)
driver.save_screenshot(tmpfilepath)
driver.quit()
initial = initial.copy()
initial['source_url'] = source_url
initial['title'] = title
initial['date'] = soup_date
initial['body'] = body
initial['source_upload'] = tmpfilepath_rel
except KeyError as e:
print("no valid source_url found. zeige also ganz normales add/new template")
except IndexError as e:
print("no valid source_url found. zeige also ganz normales add/new template")
return initial
url.py
class Site(models.Model):
def get_source_upload_path(instance, filename):
now = datetime.datetime.now()
return "appname/sites/{}/{}/{}/site_{}_{}".format(now.year, now.month, now.day, instance.pk, filename)
creationDate = models.DateTimeField(auto_now_add=True)
last_modifiedDate = models.DateTimeField(auto_now=True)
creator = models.ForeignKey('auth.User', related_name='siteCreated')
last_modifier = models.ForeignKey('auth.User', related_name='siteLast_modified')
date = models.DateTimeField(default=datetime.date.today)
title = models.CharField(max_length=240, blank=True)
body = models.TextField(max_length=3000)
source_url = models.URLField(blank=True)
source_upload = models.FileField(upload_to=get_source_upload_path, blank=True)
keywords = models.ManyToManyField("Keyword")
url(r'site/add/$', views.SiteCreate.as_view(), name='site-add'),
url(r'site/add/(?P<source_url>[A-Za-z0-9\-._~:/\[\]@!$&\'\(\)\*\+,;=?#]+)/$', views.SiteCreate.as_view(), name='site-add-fromurl'),
class SiteForm(ModelForm):
class Meta:
model = Site
fields = ['date', 'title', 'body', 'source_url', 'source_upload', 'keywords']
widgets = {
'keywords' : CheckboxSelectMultiple(),
}
class SiteCreate(LoginRequiredMixin, CreateView):
model = Site
template_name = 'appname/site_form.html'
form_class = SiteForm
success_url = reverse_lazy('appname:index')
def form_valid(self, form):
form.instance.creator = self.request.user
form.instance.last_modifier = self.request.user
return super(SiteCreate, self).form_valid(form)
def get_initial(self):
# Get the initial dictionary from the superclass method
initial = super(SiteCreate, self).get_initial()
try:
#get target url from request
fullpath = self.request.get_full_path()
fullpath = fullpath.split("/")
fullpath, querystring = fullpath[3:-1], fullpath[-1]
source_domain = fullpath[2]
fullpath = "/".join(fullpath)
fullpath += querystring
source_url = fullpath
if (not source_url.startswith("http://") and not source_url.startswith("https://")):
print("ERROR: url does not start with http:// or https://")
return initial
# ...
# extract title, date & others with BeautifulSoup
# ...
#extract screenshot (is there a better way?)
from selenium import webdriver
driver = webdriver.Firefox()
driver.get(source_url)
tmpfilename = "{}_{}.png".format(get_valid_filename(source_domain), get_valid_filename(title[:30]))
now = datetime.datetime.now()
tmpfilepath_rel = "appname/sites/tmp/{}/{}/{}/{}".format(now.year, now.month, now.day, tmpfilename)
tmpfilepath = settings.MEDIA_ROOT + tmpfilepath_rel
folder=os.path.dirname(tmpfilepath)
if not os.path.exists(folder):
os.makedirs(folder)
driver.save_screenshot(tmpfilepath)
driver.quit()
initial = initial.copy()
initial['source_url'] = source_url
initial['title'] = title
initial['date'] = soup_date
initial['body'] = body
initial['source_upload'] = tmpfilepath_rel
except KeyError as e:
print("no valid source_url found. zeige also ganz normales add/new template")
except IndexError as e:
print("no valid source_url found. zeige also ganz normales add/new template")
return initial
视图.py
class Site(models.Model):
def get_source_upload_path(instance, filename):
now = datetime.datetime.now()
return "appname/sites/{}/{}/{}/site_{}_{}".format(now.year, now.month, now.day, instance.pk, filename)
creationDate = models.DateTimeField(auto_now_add=True)
last_modifiedDate = models.DateTimeField(auto_now=True)
creator = models.ForeignKey('auth.User', related_name='siteCreated')
last_modifier = models.ForeignKey('auth.User', related_name='siteLast_modified')
date = models.DateTimeField(default=datetime.date.today)
title = models.CharField(max_length=240, blank=True)
body = models.TextField(max_length=3000)
source_url = models.URLField(blank=True)
source_upload = models.FileField(upload_to=get_source_upload_path, blank=True)
keywords = models.ManyToManyField("Keyword")
url(r'site/add/$', views.SiteCreate.as_view(), name='site-add'),
url(r'site/add/(?P<source_url>[A-Za-z0-9\-._~:/\[\]@!$&\'\(\)\*\+,;=?#]+)/$', views.SiteCreate.as_view(), name='site-add-fromurl'),
class SiteForm(ModelForm):
class Meta:
model = Site
fields = ['date', 'title', 'body', 'source_url', 'source_upload', 'keywords']
widgets = {
'keywords' : CheckboxSelectMultiple(),
}
class SiteCreate(LoginRequiredMixin, CreateView):
model = Site
template_name = 'appname/site_form.html'
form_class = SiteForm
success_url = reverse_lazy('appname:index')
def form_valid(self, form):
form.instance.creator = self.request.user
form.instance.last_modifier = self.request.user
return super(SiteCreate, self).form_valid(form)
def get_initial(self):
# Get the initial dictionary from the superclass method
initial = super(SiteCreate, self).get_initial()
try:
#get target url from request
fullpath = self.request.get_full_path()
fullpath = fullpath.split("/")
fullpath, querystring = fullpath[3:-1], fullpath[-1]
source_domain = fullpath[2]
fullpath = "/".join(fullpath)
fullpath += querystring
source_url = fullpath
if (not source_url.startswith("http://") and not source_url.startswith("https://")):
print("ERROR: url does not start with http:// or https://")
return initial
# ...
# extract title, date & others with BeautifulSoup
# ...
#extract screenshot (is there a better way?)
from selenium import webdriver
driver = webdriver.Firefox()
driver.get(source_url)
tmpfilename = "{}_{}.png".format(get_valid_filename(source_domain), get_valid_filename(title[:30]))
now = datetime.datetime.now()
tmpfilepath_rel = "appname/sites/tmp/{}/{}/{}/{}".format(now.year, now.month, now.day, tmpfilename)
tmpfilepath = settings.MEDIA_ROOT + tmpfilepath_rel
folder=os.path.dirname(tmpfilepath)
if not os.path.exists(folder):
os.makedirs(folder)
driver.save_screenshot(tmpfilepath)
driver.quit()
initial = initial.copy()
initial['source_url'] = source_url
initial['title'] = title
initial['date'] = soup_date
initial['body'] = body
initial['source_upload'] = tmpfilepath_rel
except KeyError as e:
print("no valid source_url found. zeige also ganz normales add/new template")
except IndexError as e:
print("no valid source_url found. zeige also ganz normales add/new template")
return initial
site_form.html(用于创建和更新视图)
{%extends“appname/base.html”%}
{%load staticfiles%}
{%块头%}
{%endblock%}
{%block body%}
{%csrf_令牌%}
{{form.date.errors}
{{form.date.label_tag}
{{form.date}}
{{{form.date.help_text}
{{form.title.errors}}
{{form.title.label_tag}
{{form.title}}
{{{form.title.help_text}
{{form.body.errors}}
{{form.body.label_tag}
{{form.body}}
{{form.body.help_text}
{{form.source_url.errors}
{{form.source\u url.label\u tag}
{{form.source\u url}}
{{{form.source\u url.help\u text}
{{form.source_upload.errors}
{{form.source\u upload.label\u tag}
{{form.source\u upload}}
{{{form.source\u upload.help\u text}
{{form.keywords.errors}
{{form.keywords.label_tag}
{kw的%form.keywords%}
-
{{kw.tag}
{{kw.choice_label}
{%endfor%}
{{form.keywords.help_text}
{%if site.pk%}
创建人:{site.creator}
创建日期:{site.creationDate}
上次修改人:{site.Last_modifier}
上次修改日期:{site.Last_modifiedDate}
现在:{%Now“Y-m-dh:i:s”%}
{%else%}
这是一个新网站
现在:{%Now“Y-m-dh:i:s”%}
{%endif%}
{%endblock%}
这是因为表单使用的FileField的值不仅仅是文件的路径,它是FieldFile的一个实例(请参阅)
我不确定是否可以直接实例化FieldFile,但至少可以通过实例化模型来实现(不需要保存它)
在views.py中:
tmp_site = Site(source_upload=tmpfilepath_rel)
initial['source_upload'] = tmp_site.source_upload
或者,您可以在呈现html时手动添加文件链接:
<div class="currently"><a href="{{ form.source_upload.value }}">{{ form.source_upload.value }}</a></div>
我认为您不能,因为这将是一个巨大的安全风险。想象文件字段具有初始值/etc/shadow
并隐藏。这将允许您从用户系统“窃取”任何文件。我不知道javascript是怎么回事。我认为浏览器忽略了文件字段的初始值(来自html部分),我不想为“要上传的文件”设置初始值。(默认的django-)小部件类似于:“当前文件:。您可以将其替换为”
。我只想为
部分设置一个初始值。不是用户上传的本地文件(可能是也可能不是)。我不想为“要上传的文件”设置初始值,而是为FileInput小部件的“当前上传的是此文件”部分设置初始值。小部件的外观如下:“当前文件:。您可以将其替换为”
。我只想为
部分设置一个初始值。不适用于用户(可能或可能不)上载的本地文件。我对这个问题的措辞有点不清晰。你在问题中添加了html模板吗?我在问题中添加了site\u form.html
模板。