updated documentation
This commit is contained in:
parent
00875c0d8e
commit
d9feb61e85
@ -114,7 +114,8 @@ class UserPreference(models.Model):
|
|||||||
class Storage(models.Model):
|
class Storage(models.Model):
|
||||||
DROPBOX = 'DB'
|
DROPBOX = 'DB'
|
||||||
NEXTCLOUD = 'NEXTCLOUD'
|
NEXTCLOUD = 'NEXTCLOUD'
|
||||||
STORAGE_TYPES = ((DROPBOX, 'Dropbox'), (NEXTCLOUD, 'Nextcloud'))
|
LOCAL = 'LOCAL'
|
||||||
|
STORAGE_TYPES = ((DROPBOX, 'Dropbox'), (NEXTCLOUD, 'Nextcloud'), (LOCAL, 'Local'))
|
||||||
|
|
||||||
name = models.CharField(max_length=128)
|
name = models.CharField(max_length=128)
|
||||||
method = models.CharField(
|
method = models.CharField(
|
||||||
|
59
cookbook/provider/local.py
Normal file
59
cookbook/provider/local.py
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
import io
|
||||||
|
import os
|
||||||
|
import tempfile
|
||||||
|
from datetime import datetime
|
||||||
|
from os import listdir
|
||||||
|
from os.path import isfile, join
|
||||||
|
|
||||||
|
from cookbook.models import Recipe, RecipeImport, SyncLog
|
||||||
|
from cookbook.provider.provider import Provider
|
||||||
|
|
||||||
|
|
||||||
|
class Local(Provider):
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def import_all(monitor):
|
||||||
|
files = [f for f in listdir(monitor.path) if isfile(join(monitor.path, f))]
|
||||||
|
|
||||||
|
import_count = 0
|
||||||
|
for file in files:
|
||||||
|
path = monitor.path + '/' + file
|
||||||
|
if not Recipe.objects.filter(file_path__iexact=path).exists() \
|
||||||
|
and not RecipeImport.objects.filter(file_path=path).exists(): # noqa: E501
|
||||||
|
name = os.path.splitext(file)[0]
|
||||||
|
new_recipe = RecipeImport(
|
||||||
|
name=name,
|
||||||
|
file_path=path,
|
||||||
|
storage=monitor.storage
|
||||||
|
)
|
||||||
|
new_recipe.save()
|
||||||
|
import_count += 1
|
||||||
|
|
||||||
|
log_entry = SyncLog(
|
||||||
|
status='SUCCESS',
|
||||||
|
msg='Imported ' + str(import_count) + ' recipes',
|
||||||
|
sync=monitor
|
||||||
|
)
|
||||||
|
log_entry.save()
|
||||||
|
|
||||||
|
monitor.last_checked = datetime.now()
|
||||||
|
monitor.save()
|
||||||
|
|
||||||
|
return True
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def get_file(recipe):
|
||||||
|
file = io.BytesIO(open(recipe.file_path, 'rb').read())
|
||||||
|
|
||||||
|
return file
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def rename_file(recipe, new_name):
|
||||||
|
os.rename(recipe.file_path, os.path.join(os.path.dirname(recipe.file_path), (new_name + os.path.splitext(recipe.file_path)[1])))
|
||||||
|
|
||||||
|
return True
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def delete_file(recipe):
|
||||||
|
os.remove(recipe.file_path)
|
||||||
|
return True
|
@ -38,6 +38,7 @@ from cookbook.models import (CookLog, Food, Ingredient, Keyword, MealPlan,
|
|||||||
Storage, Sync, SyncLog, Unit, UserPreference,
|
Storage, Sync, SyncLog, Unit, UserPreference,
|
||||||
ViewLog, RecipeBookEntry)
|
ViewLog, RecipeBookEntry)
|
||||||
from cookbook.provider.dropbox import Dropbox
|
from cookbook.provider.dropbox import Dropbox
|
||||||
|
from cookbook.provider.local import Local
|
||||||
from cookbook.provider.nextcloud import Nextcloud
|
from cookbook.provider.nextcloud import Nextcloud
|
||||||
from cookbook.serializer import (FoodSerializer, IngredientSerializer,
|
from cookbook.serializer import (FoodSerializer, IngredientSerializer,
|
||||||
KeywordSerializer, MealPlanSerializer,
|
KeywordSerializer, MealPlanSerializer,
|
||||||
@ -370,6 +371,8 @@ def get_recipe_provider(recipe):
|
|||||||
return Dropbox
|
return Dropbox
|
||||||
elif recipe.storage.method == Storage.NEXTCLOUD:
|
elif recipe.storage.method == Storage.NEXTCLOUD:
|
||||||
return Nextcloud
|
return Nextcloud
|
||||||
|
elif recipe.storage.method == Storage.LOCAL:
|
||||||
|
return Local
|
||||||
else:
|
else:
|
||||||
raise Exception('Provider not implemented')
|
raise Exception('Provider not implemented')
|
||||||
|
|
||||||
@ -394,8 +397,8 @@ def get_external_file_link(request, recipe_id):
|
|||||||
@group_required('user')
|
@group_required('user')
|
||||||
def get_recipe_file(request, recipe_id):
|
def get_recipe_file(request, recipe_id):
|
||||||
recipe = Recipe.objects.get(id=recipe_id)
|
recipe = Recipe.objects.get(id=recipe_id)
|
||||||
if not recipe.cors_link:
|
# if not recipe.cors_link:
|
||||||
update_recipe_links(recipe)
|
# update_recipe_links(recipe)
|
||||||
|
|
||||||
return FileResponse(get_recipe_provider(recipe).get_file(recipe))
|
return FileResponse(get_recipe_provider(recipe).get_file(recipe))
|
||||||
|
|
||||||
@ -420,6 +423,10 @@ def sync_all(request):
|
|||||||
ret = Nextcloud.import_all(monitor)
|
ret = Nextcloud.import_all(monitor)
|
||||||
if not ret:
|
if not ret:
|
||||||
error = True
|
error = True
|
||||||
|
if monitor.storage.method == Storage.LOCAL:
|
||||||
|
ret = Local.import_all(monitor)
|
||||||
|
if not ret:
|
||||||
|
error = True
|
||||||
|
|
||||||
if not error:
|
if not error:
|
||||||
messages.add_message(
|
messages.add_message(
|
||||||
|
@ -13,6 +13,7 @@ from cookbook.models import (Comment, InviteLink, Keyword, MealPlan, Recipe,
|
|||||||
RecipeBook, RecipeBookEntry, RecipeImport,
|
RecipeBook, RecipeBookEntry, RecipeImport,
|
||||||
Storage, Sync)
|
Storage, Sync)
|
||||||
from cookbook.provider.dropbox import Dropbox
|
from cookbook.provider.dropbox import Dropbox
|
||||||
|
from cookbook.provider.local import Local
|
||||||
from cookbook.provider.nextcloud import Nextcloud
|
from cookbook.provider.nextcloud import Nextcloud
|
||||||
|
|
||||||
|
|
||||||
@ -37,6 +38,8 @@ def delete_recipe_source(request, pk):
|
|||||||
Dropbox.delete_file(recipe)
|
Dropbox.delete_file(recipe)
|
||||||
if recipe.storage.method == Storage.NEXTCLOUD:
|
if recipe.storage.method == Storage.NEXTCLOUD:
|
||||||
Nextcloud.delete_file(recipe)
|
Nextcloud.delete_file(recipe)
|
||||||
|
if recipe.storage.method == Storage.LOCAL:
|
||||||
|
Local.delete_file(recipe)
|
||||||
|
|
||||||
recipe.storage = None
|
recipe.storage = None
|
||||||
recipe.file_path = ''
|
recipe.file_path = ''
|
||||||
|
@ -18,6 +18,7 @@ from cookbook.models import (Comment, Food, Ingredient, Keyword, MealPlan,
|
|||||||
MealType, Recipe, RecipeBook, RecipeImport,
|
MealType, Recipe, RecipeBook, RecipeImport,
|
||||||
Storage, Sync)
|
Storage, Sync)
|
||||||
from cookbook.provider.dropbox import Dropbox
|
from cookbook.provider.dropbox import Dropbox
|
||||||
|
from cookbook.provider.local import Local
|
||||||
from cookbook.provider.nextcloud import Nextcloud
|
from cookbook.provider.nextcloud import Nextcloud
|
||||||
|
|
||||||
|
|
||||||
@ -231,6 +232,8 @@ class ExternalRecipeUpdate(GroupRequiredMixin, UpdateView):
|
|||||||
Dropbox.rename_file(old_recipe, self.object.name)
|
Dropbox.rename_file(old_recipe, self.object.name)
|
||||||
if self.object.storage.method == Storage.NEXTCLOUD:
|
if self.object.storage.method == Storage.NEXTCLOUD:
|
||||||
Nextcloud.rename_file(old_recipe, self.object.name)
|
Nextcloud.rename_file(old_recipe, self.object.name)
|
||||||
|
if self.object.storage.method == Storage.LOCAL:
|
||||||
|
Local.rename_file(old_recipe, self.object.name)
|
||||||
|
|
||||||
self.object.file_path = "%s/%s%s" % (
|
self.object.file_path = "%s/%s%s" % (
|
||||||
os.path.dirname(self.object.file_path),
|
os.path.dirname(self.object.file_path),
|
||||||
|
@ -12,9 +12,6 @@ Lastly you will need to sync with the external path and import recipes you desir
|
|||||||
|
|
||||||
## Storage
|
## Storage
|
||||||
|
|
||||||
!!! success
|
|
||||||
Currently only Nextcloud and Dropbox are supported. There are plans to add more provider
|
|
||||||
|
|
||||||
!!! danger
|
!!! danger
|
||||||
In order for this application to retrieve data from external providers it needs to store authentication information.
|
In order for this application to retrieve data from external providers it needs to store authentication information.
|
||||||
Please use read only/separate accounts or app passwords wherever possible.
|
Please use read only/separate accounts or app passwords wherever possible.
|
||||||
@ -31,6 +28,24 @@ The basic configuration is the same for all providers.
|
|||||||
| Name | Your identifier for this storage source, can be everything you want. |
|
| Name | Your identifier for this storage source, can be everything you want. |
|
||||||
| Method | The desired method. |
|
| Method | The desired method. |
|
||||||
|
|
||||||
|
!!! success
|
||||||
|
Only the providers listed below are currently implemented. If you need anything else feel free to open
|
||||||
|
an issue or pull request.
|
||||||
|
|
||||||
|
### Local
|
||||||
|
|
||||||
|
!!! info
|
||||||
|
There is currently no way to upload files trough the webinterface. This is a feature that might be added later.
|
||||||
|
|
||||||
|
The local provider does not need any configuration.
|
||||||
|
For the monitor you will need to define a valid path on your host system.
|
||||||
|
The Path depends on your setup and can be both relative and absoulte.
|
||||||
|
If you use docker the default directory is `/opt/recipes/`
|
||||||
|
|
||||||
|
!!! warning "Volume"
|
||||||
|
By default no data other than the mediafiles and the database is persisted. If you use the local provider
|
||||||
|
make sure to mount the path you choose to monitor to your host system in order to keep it persistent.
|
||||||
|
|
||||||
### Dropbox
|
### Dropbox
|
||||||
|
|
||||||
| Field | Value |
|
| Field | Value |
|
||||||
|
Loading…
Reference in New Issue
Block a user