This commit is contained in:
vabene1111
2019-11-14 10:06:51 +01:00
parent a6ce4edc93
commit 9a22c37862
6 changed files with 124 additions and 18 deletions

View File

@@ -1,15 +1,18 @@
# Recipies
Recipes is a Django application that allows categorization and tagging of arbitrary numbers of recipes (or in fact any other file) in a storage backend.
Currently the only supported storage backend is dropbox, but this can easily be changed as the system is modular and already has fields to support different backends.
Recipes is a Django application that allows tagging of arbitrary numbers of recipes (or in fact any other file) in a storage backend.
It also allows the easy creation of recipes directly on the page.
Currently the only supported storage backend is dropbox, but this can easily be changed as the system is modular and
already has fields to support different backends.
## Usage
Most things should be straight forward but there are some more complicated things.
##### General
Create Categories and Keywords under the `New` tab. You can have a simple look at most Tables under the `List` Tab.
Management options for your Data are under `Manage Data`
Different kinds of objects, like tags or storage backends, can be viewed under the lists tab. This is also were you create
new objects by pressing the plus button.
Management options for your data, like batch edits and import logs, can be found under `Manage Data`.
##### Storage Backends
Currently only dropbox is supported as a storage backend. To add a new Dropbox go to `New >> Storage Backend` and enter
a name (just a display name for you to identify it) and an API access Token for the account you want to use.
Currently only dropbox is supported as a storage backend. To add a new Dropbox go to `Lists >> Storage Backend` and add a new backend.
Enter a name (just a display name for you to identify it) and an API access Token for the account you want to use.
You can obtain the API token on [Dropboxes API explorer](https://dropbox.github.io/dropbox-api-v2-explorer/#auth_token/from_oauth1)
with the button on the top right.
##### Adding Synced Path's
@@ -18,28 +21,37 @@ Then enter the path you want to monitor starting at the storage root (e.g. `/Fol
##### Syncing Data
To sync the recipes app with the storage backends press `Sync now` under `Manage Data >> Configure Sync`.
##### Import Recipes
All files found by the sync can be found under `List >> New Recipes`. There you can either import all at once without
All files found by the sync can be found under `Manage Data >> Import recipes`. There you can either import all at once without
modifying them or import one by one, adding Category and Tags while importing.
##### Batch Edit
If you have many uncategorized and untagged recipes you may want to edit them all at once. For this go to
`Manage Data >> Batch Edit`. Enter a word which should be contained in the recipe name and select category and tags.
If you have many untagged recipes you may want to edit them all at once. For this go to
`Manage Data >> Batch Edit`. Enter a word which should be contained in the recipe name and select the tags you want to apply.
When clicking submit every recipe containing the word will be updated (tags are added).
> Currently the only option is word contains, maybe some more SQL like operators will be added later.
## Installation
If you want to *install* the application for usage use a tutorial of your choice
(for example this one http://uwsgi-docs.readthedocs.io/en/latest/tutorials/Django_and_nginx.html)
on deploying django applications.
### Docker-Compose
A docker-compose file is included in the repository. It is made for setups already running an nginx-reverse proxy network with
lets encrypt companion. Copy `.env.template` to `.env` and fill in the missing values accordingly.
Now simply start the containers and run the `update.sh` script which will apply all migrations and collect static files.
Create a default user by executing into the container with `docker-compose exec web_recipes sh` and run `python3 manage.py createsuperuser`.
### Manual
Copy `.env.template` to `.env` and fill in the missing values accordingly.
You can leave out the docker specific variables (VIRTUAL_HOST, LETSENCRYPT_HOST, LETSENCRYPT_EMAIL).
Make sure all variables are available to whatever servers your application.
Otherwise simply follow the instructions for any django based deployment
(for example this one http://uwsgi-docs.readthedocs.io/en/latest/tutorials/Django_and_nginx.html).
To start developing:
1. Clone the repository using your preferred method
2. Install requirements from `requirements.txt` either globally or in a virtual environment
3. Copy `secret_settings.template` to `secret_settings.py`
4. Configure preferred database backend in `secret_settings.py`, default is sqlite
5. Run migrations with `manage.py migrate`
6. Create a first user with `manage.py createsuperuser`
7. Start development server with `manage.py runserver`
3. Run migrations with `manage.py migrate`
4. Create a first user with `manage.py createsuperuser`
5. Start development server with `manage.py runserver`
## Contributing
Pull Requests and ideas are welcome, feel free to contribute in any way.

View File

@@ -46,6 +46,19 @@ class InternalRecipeForm(forms.ModelForm):
widgets = {'keywords': MultiSelectWidget}
class CommentForm(forms.ModelForm):
class Meta:
model = Comment
fields = ('text', )
labels = {
'text': _('Add your comment: '),
}
widgets = {
'text': forms.Textarea(attrs={'rows': 2, 'cols': 15}),
}
class KeywordForm(forms.ModelForm):
class Meta:
model = Keyword

View File

@@ -0,0 +1,27 @@
# Generated by Django 2.2.7 on 2019-11-14 08:49
from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
('cookbook', '0005_recipeingredients_amount'),
]
operations = [
migrations.CreateModel(
name='Comment',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('text', models.TextField()),
('created_at', models.DateTimeField(auto_now_add=True)),
('updated_at', models.DateTimeField(auto_now=True)),
('created_by', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)),
('recipe', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='cookbook.Recipe')),
],
),
]

View File

@@ -1,3 +1,4 @@
from django.contrib.auth.models import User
from django.db import models
@@ -77,6 +78,14 @@ class RecipeIngredients(models.Model):
ingredient = models.ForeignKey(Ingredients, models.PROTECT)
class Comment(models.Model):
recipe = models.ForeignKey(Recipe, on_delete=models.CASCADE)
text = models.TextField()
created_by = models.ForeignKey(User, on_delete=models.CASCADE)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
class RecipeImport(models.Model):
name = models.CharField(max_length=128)
storage = models.ForeignKey(Storage, on_delete=models.PROTECT)

View File

@@ -29,4 +29,27 @@
{{ recipe.instructions | markdown | safe }}
<br/>
<br/>
<h5>{% trans 'Comments' %}</h5>
<form method="POST" class="post-form">
{% csrf_token %}
{{ form|crispy }}
<input type="submit" value="Submit" class="btn btn-success">
</form>
{% for c in comments %}
<div class="card">
<div class="card-body">
<small class="card-title">{{ c.updated_at }} {% trans 'by' %} {{ c.created_by.username }}</small> <br/>
{{ c.text }}
</div>
<br/>
</div>
{% endfor %}
{% endblock %}

View File

@@ -1,6 +1,10 @@
from django.contrib import messages
from django.contrib.auth.decorators import login_required
from django.http import HttpResponseRedirect
from django.shortcuts import render, get_object_or_404
from django.urls import reverse
from django_tables2 import RequestConfig
from django.utils.translation import gettext as _
from cookbook.filters import RecipeFilter
from cookbook.forms import *
@@ -23,8 +27,26 @@ def index(request):
def recipe_view(request, pk):
recipe = get_object_or_404(Recipe, pk=pk)
ingredients = RecipeIngredients.objects.filter(recipe=recipe)
comments = Comment.objects.filter(recipe=recipe)
return render(request, 'recipe_view.html', {'recipe': recipe, 'ingredients': ingredients})
if request.method == "POST":
form = CommentForm(request.POST)
if form.is_valid():
comment = Comment()
comment.recipe = recipe
comment.text = form.cleaned_data['text']
comment.created_by = request.user
comment.save()
messages.add_message(request, messages.SUCCESS, _('Comment saved!'))
return HttpResponseRedirect(reverse('view_recipe', args=[pk]))
else:
messages.add_message(request, messages.ERROR, _('There was an error saving this comment!'))
else:
form = CommentForm()
return render(request, 'recipe_view.html', {'recipe': recipe, 'ingredients': ingredients, 'comments': comments, 'form': form})
def test(request):