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
模板。