Repository: pretalx/pretalx

Issue:
Resource without a resource (FileField) addressed
## Current Behavior

A resource with an empty FileField causes `active_resources` to return resources that have an empty `FileField` which then crashes the talk views.

I'm not sure how this `Resource` instance occurred in our database, but I suspect something like a rejected file, broken transfer etc. to have caused it.

## Expected Behavior

Properties of empty string `FIleField` are skipped. I think it's fixed by doing this:

```
    @property
    def active_resources(self):
        return self.resources.filter(resource__isnull=False)
```

change to:

```
    @property
    def active_resources(self):
        return self.resources.exclude(resource="").exclude(resource=None)
```

## Steps to Reproduce

Create a `Resource` instance for a submission with empty string in the `resource` field.

## Context

DjangoCon Europe 2019 - currently happening in ` /conference/talk/8LMBGP/`

```
In [3]: models.Submission.objects.filter(code="8LMBGP")[0]                                                                                    
Out[3]: <Submission: Submission(event=conference, code=8LMBGP, title=Building a custom model field from the ground up, state=confirmed)>

In [4]: models.Submission.objects.filter(code="8LMBGP")[0].active_resources                                                                   
Out[4]: <QuerySet [<Resource: Resource(event=conference, submission=Building a custom model field from the ground up)>]>

In [5]: models.Submission.objects.filter(code="8LMBGP")[0].active_resources[0]                                                                
Out[5]: <Resource: Resource(event=conference, submission=Building a custom model field from the ground up)>

In [6]: models.Submission.objects.filter(code="8LMBGP")[0].active_resources[0].resource                                                       
Out[6]: <FieldFile: None>

In [7]: models.Submission.objects.filter(code="8LMBGP")[0].active_resources[0].resource.path                                                  
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-7-6cb30323695b> in <module>
----> 1 models.Submission.objects.filter(code="8LMBGP")[0].active_resources[0].resource.path

~/.virtualenvs/venv/lib/python3.6/site-packages/django/db/models/fields/files.py in path(self)
     54     @property
     55     def path(self):
---> 56         self._require_file()
     57         return self.storage.path(self.name)
     58 

~/.virtualenvs/venv/lib/python3.6/site-packages/django/db/models/fields/files.py in _require_file(self)
     36     def _require_file(self):
     37         if not self:
---> 38             raise ValueError("The '%s' attribute has no file associated with it." % self.field.name)
     39 
     40     def _get_file(self):

ValueError: The 'resource' attribute has no file associated with it.
```

## Your Environment

```
Traceback:
File "venv/lib/python3.6/site-packages/django/template/base.py" in _resolve_lookup
  829.                     current = current[bit]
During handling of the above exception ('FieldFile' object is not subscriptable), another exception occurred:
File "venv/lib/python3.6/site-packages/django/core/handlers/exception.py" in inner
  34.             response = get_response(request)
File "venv/lib/python3.6/site-packages/django/core/handlers/base.py" in _get_response
  156.                 response = self.process_exception_by_middleware(e, request)
File "venv/lib/python3.6/site-packages/django/core/handlers/base.py" in _get_response
  154.                 response = response.render()
File "venv/lib/python3.6/site-packages/django/template/response.py" in render
  106.             self.content = self.rendered_content
File "venv/lib/python3.6/site-packages/django/template/response.py" in rendered_content
  83.         content = template.render(context, self._request)
File "venv/lib/python3.6/site-packages/django/template/backends/django.py" in render
  61.             return self.template.render(context)
File "venv/lib/python3.6/site-packages/django/template/base.py" in render
  171.                     return self._render(context)
File "venv/lib/python3.6/site-packages/django/template/base.py" in _render
  163.         return self.nodelist.render(context)
File "venv/lib/python3.6/site-packages/django/template/base.py" in render
  937.                 bit = node.render_annotated(context)
File "venv/lib/python3.6/site-packages/django/template/base.py" in render_annotated
  904.             return self.render(context)
File "venv/lib/python3.6/site-packages/django/template/loader_tags.py" in render
  150.             return compiled_parent._render(context)
File "venv/lib/python3.6/site-packages/django/template/base.py" in _render
  163.         return self.nodelist.render(context)
File "venv/lib/python3.6/site-packages/django/template/base.py" in render
  937.                 bit = node.render_annotated(context)
File "venv/lib/python3.6/site-packages/django/template/base.py" in render_annotated
  904.             return self.render(context)
File "venv/lib/python3.6/site-packages/django/template/loader_tags.py" in render
  150.             return compiled_parent._render(context)
File "venv/lib/python3.6/site-packages/django/template/base.py" in _render
  163.         return self.nodelist.render(context)
File "venv/lib/python3.6/site-packages/django/template/base.py" in render
  937.                 bit = node.render_annotated(context)
File "venv/lib/python3.6/site-packages/django/template/base.py" in render_annotated
  904.             return self.render(context)
File "venv/lib/python3.6/site-packages/django/template/loader_tags.py" in render
  62.                 result = block.nodelist.render(context)
File "venv/lib/python3.6/site-packages/django/template/base.py" in render
  937.                 bit = node.render_annotated(context)
File "venv/lib/python3.6/site-packages/django/template/base.py" in render_annotated
  904.             return self.render(context)
File "venv/lib/python3.6/site-packages/django/template/loader_tags.py" in render
  62.                 result = block.nodelist.render(context)
File "venv/lib/python3.6/site-packages/django/template/base.py" in render
  937.                 bit = node.render_annotated(context)
File "venv/lib/python3.6/site-packages/django/template/base.py" in render_annotated
  904.             return self.render(context)
File "venv/lib/python3.6/site-packages/django/template/defaulttags.py" in render
  309.                 return nodelist.render(context)
File "venv/lib/python3.6/site-packages/django/template/base.py" in render
  937.                 bit = node.render_annotated(context)
File "venv/lib/python3.6/site-packages/django/template/base.py" in render_annotated
  904.             return self.render(context)
File "venv/lib/python3.6/site-packages/django/template/defaulttags.py" in render
  309.                 return nodelist.render(context)
File "venv/lib/python3.6/site-packages/django/template/base.py" in render
  937.                 bit = node.render_annotated(context)
File "venv/lib/python3.6/site-packages/django/template/base.py" in render_annotated
  904.             return self.render(context)
File "venv/lib/python3.6/site-packages/django/template/base.py" in render
  987.             output = self.filter_expression.resolve(context)
File "venv/lib/python3.6/site-packages/django/template/base.py" in resolve
  671.                 obj = self.var.resolve(context)
File "venv/lib/python3.6/site-packages/django/template/base.py" in resolve
  796.             value = self._resolve_lookup(context)
File "venv/lib/python3.6/site-packages/django/template/base.py" in _resolve_lookup
  837.                         current = getattr(current, bit)
File "venv/lib/python3.6/site-packages/django/db/models/fields/files.py" in url
  61.         self._require_file()
File "venv/lib/python3.6/site-packages/django/db/models/fields/files.py" in _require_file
  38.             raise ValueError("The '%s' attribute has no file associated with it." % self.field.name)
Exception Type: ValueError at /conference/talk/8LMBGP/
Exception Value: The 'resource' attribute has no file associated with it.
Request information:
USER: AnonymousUser
```



Discussion:
Empty resources could be created in v0.9.0, but this issue has been fixed in master.

Resolving patch:
diff --git a/src/pretalx/submission/models/submission.py b/src/pretalx/submission/models/submission.py
--- a/src/pretalx/submission/models/submission.py
+++ b/src/pretalx/submission/models/submission.py
@@ -476,7 +476,7 @@ def median_score(self):
 
     @cached_property
     def active_resources(self):
-        return self.resources.filter(resource__isnull=False)
+        return self.resources.exclude(resource=None).exclude(resource="")
 
     @property
     def is_deleted(self):


Test patch: