Attachment files dispatching is now done through `RawAttachmentView`
view that checks for appropiate permissions.
When using the development server this view just redirects to the real
media path of the file.
When using the production server the special redirection header
`X-Accel-Redirect` is used instead to improve efficiency by instructing
the server to dispatch the file instead of django, but you also need the
following configuration (Nginx):
location /attachment-files {
internal;
alias /path/to/taiga/media/attachment-files;
}
It's recommended to also restrict the direct access from outside to the
`attachment-files` directory by using some configuration like this:
location /media/attachment-files {
deny all;
}
First update taiga-vagrant vm if you're using it, you will have access
to the rabbit management console at port 8001 of the host machine.
* Defining tasks
- Tasks must be defined in a `deferred` module of an app, for example,
`taiga.projects.deferred` module.
- Tasks must be decorated and given the name "<app>.<task-name>", for
example in `taiga.projects.deferred` module:
```
from taiga.celery import app
@app.task(name="projects.add")
def add(x, y):
return x + y
```
- Tasks should be at most just wrappers around service functions to
promote re-usability of those functions from other parts of the code,
say, management commands and the like.
* Calling tasks
Tasks should be called using one of the three functions defined in
`taiga.deferred` module:
- `defer`: Use this function if you need to perform some task
asynchronously and GET THE RESULT back later, for example:
```
result = defer("projects.add", x=1, y=2)
...
result.get() # => 3
```
- `call_async`: Use this function when you want to fire off some
task. No result is get back. For example:
```
call_async("projects.email_user", user)
```
- `apply_async`: Is the same as `call_async` but since it's a function
application and you must pass the args and kwargs together as one
parameter each you are allowed to pass celery-specific
extra-options (but bear in mind this is not recommended!)
```
apply_async("projects.email_user", args=(user,), kwargs={}, routing_key="tasks.email")
```
We are already using pg arrays so the unpickle function in sql/tags.sql
is not needed, at least by the moment. I'm removing it because it was
entering in an infinite loop when creating the test database.
The stars application has been removed in favor of a more generic voting
application that works with any model. Starring a project is just a
special case of voting a project.
Usage.
Add a vote:
votes.add_vote(<model instance>, user)
Remove a vote:
votes.remove_vote(<model instance>, user)
Get the queryset of users that voted an object:
votes.get_voters(<model instance>)
Get the number of votes an object has:
votes.get_votes(<model instance>)
Get the objects of type <model> voted by an user:
votes.get_voted(user, <model>)
The issues application is already making use of the votes application
through the following urls:
/api/v1/issues/<id>/upvote <- url name is "issues-upvote"
/api/v1/issues/<id>/downvote <- url name is "issues-downvote"
List project fans:
/projects/<project id>/fans
/projects/<project id>/fans/<user id>
List user starred projects:
/users/<user id>/starred
/users/<user id>/starred/<project id>
Also a "star" field with the stars count of a project is included in the
project detail and list responses.